]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.48 1.3.48
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:26 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:26 +0000 (15:10 -0500)
174 files changed:
Documentation/filesystems/hpfs.txt
Makefile
arch/alpha/boot/main.c
arch/alpha/defconfig
arch/alpha/kernel/bios32.c
arch/alpha/kernel/setup.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/i386/boot/compressed/Makefile
arch/i386/boot/compressed/Makefile.debug [new file with mode: 0644]
arch/i386/boot/compressed/crypt.h [deleted file]
arch/i386/boot/compressed/gzip.h [deleted file]
arch/i386/boot/compressed/inflate.c [deleted file]
arch/i386/boot/compressed/lzw.h [deleted file]
arch/i386/boot/compressed/misc.c
arch/i386/boot/compressed/unzip.c [deleted file]
arch/i386/kernel/setup.c
arch/mips/Makefile
arch/mips/boot/Makefile
arch/mips/config.in
arch/mips/defconfig [new file with mode: 0644]
arch/mips/kernel/Makefile
arch/mips/kernel/cache.S [deleted file]
arch/mips/kernel/entry.S
arch/mips/kernel/gdb-low.S [new file with mode: 0644]
arch/mips/kernel/gdb-stub.c [new file with mode: 0644]
arch/mips/kernel/head.S
arch/mips/kernel/ioport.c
arch/mips/kernel/ipc.c [new file with mode: 0644]
arch/mips/kernel/irq.c
arch/mips/kernel/jazz-c.c [new file with mode: 0644]
arch/mips/kernel/jazzdma.c [new file with mode: 0644]
arch/mips/kernel/magnum4000.S [new file with mode: 0644]
arch/mips/kernel/pica.S [new file with mode: 0644]
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/r4xx0.S [new file with mode: 0644]
arch/mips/kernel/resume.S [deleted file]
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/syscall.c [new file with mode: 0644]
arch/mips/kernel/syscalls.h [new file with mode: 0644]
arch/mips/kernel/sysmips.c [new file with mode: 0644]
arch/mips/kernel/time.c [new file with mode: 0644]
arch/mips/kernel/tlb.S [deleted file]
arch/mips/kernel/traps.c
arch/mips/kernel/tyne-c.c [new file with mode: 0644]
arch/mips/kernel/tyne.S [new file with mode: 0644]
arch/mips/kernel/tynedma.c [deleted file]
arch/mips/ld.script [new file with mode: 0644]
arch/mips/lib/Makefile [new file with mode: 0644]
arch/mips/lib/checksum.c [new file with mode: 0644]
arch/mips/mm/Makefile
arch/mips/mm/fault.c
arch/mips/mm/init.c
drivers/Makefile
drivers/block/Makefile
drivers/block/README.ide
drivers/block/cmd640.c
drivers/block/genhd.c
drivers/block/ide-tape.c
drivers/block/ide-tape.h
drivers/block/ide.c
drivers/block/ide.h
drivers/block/ll_rw_blk.c
drivers/block/ramdisk.c [deleted file]
drivers/block/rd.c [new file with mode: 0644]
drivers/block/triton.c
drivers/cdrom/cdu31a.c
drivers/cdrom/sbpcd.c
drivers/char/ChangeLog
drivers/char/busmouse.c
drivers/char/serial.c
drivers/net/8390.c
drivers/net/de4x5.c
drivers/net/ewrk3.c
drivers/net/znet.c
drivers/scsi/Config.in
drivers/scsi/Makefile
drivers/scsi/README.st
drivers/scsi/aha152x.c
drivers/scsi/aha152x.h
drivers/scsi/constants.c
drivers/scsi/g_NCR5380.c
drivers/scsi/g_NCR5380.h
drivers/scsi/pas16.c
drivers/scsi/pas16.h
drivers/scsi/st.c
drivers/scsi/st.h
drivers/scsi/st_options.h
drivers/scsi/t128.c
drivers/scsi/t128.h
fs/buffer.c
fs/hpfs/hpfs_fs.c
fs/inode.c
fs/msdos/file.c
fs/msdos/inode.c
fs/msdos/namei.c
fs/namei.c
fs/open.c
fs/umsdos/inode.c
include/asm-alpha/pgtable.h
include/asm-alpha/processor.h
include/asm-alpha/termios.h
include/asm-i386/bugs.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/termios.h
include/asm-mips/a.out.h [new file with mode: 0644]
include/asm-mips/asm.h [new file with mode: 0644]
include/asm-mips/bitops.h
include/asm-mips/bootinfo.h
include/asm-mips/byteorder.h
include/asm-mips/cachectl.h
include/asm-mips/checksum.h [new file with mode: 0644]
include/asm-mips/delay.h
include/asm-mips/dma.h
include/asm-mips/elf.h [new file with mode: 0644]
include/asm-mips/errno.h [new file with mode: 0644]
include/asm-mips/fcntl.h [new file with mode: 0644]
include/asm-mips/floppy.h
include/asm-mips/fpregdef.h [new file with mode: 0644]
include/asm-mips/gdb-stub.h [new file with mode: 0644]
include/asm-mips/io.h
include/asm-mips/ioctl.h [new file with mode: 0644]
include/asm-mips/ioctls.h [new file with mode: 0644]
include/asm-mips/irq.h
include/asm-mips/jazz.h [new file with mode: 0644]
include/asm-mips/jazzdma.h [new file with mode: 0644]
include/asm-mips/mc146818rtc.h [new file with mode: 0644]
include/asm-mips/mipsconfig.h
include/asm-mips/mipsregs.h
include/asm-mips/mman.h [new file with mode: 0644]
include/asm-mips/page.h
include/asm-mips/pgtable.h [new file with mode: 0644]
include/asm-mips/pica.h [new file with mode: 0644]
include/asm-mips/processor.h
include/asm-mips/ptrace.h
include/asm-mips/reg.h [new file with mode: 0644]
include/asm-mips/regdef.h
include/asm-mips/resource.h [new file with mode: 0644]
include/asm-mips/segment.h
include/asm-mips/shmparam.h [new file with mode: 0644]
include/asm-mips/sigcontext.h [new file with mode: 0644]
include/asm-mips/signal.h
include/asm-mips/socket.h [new file with mode: 0644]
include/asm-mips/stackframe.h
include/asm-mips/stat.h [new file with mode: 0644]
include/asm-mips/statfs.h [new file with mode: 0644]
include/asm-mips/string.h
include/asm-mips/sysmips.h [new file with mode: 0644]
include/asm-mips/system.h
include/asm-mips/termbits.h [new file with mode: 0644]
include/asm-mips/termios.h [new file with mode: 0644]
include/asm-mips/types.h
include/asm-mips/unistd.h
include/asm-mips/user.h [new file with mode: 0644]
include/asm-mips/vector.h [new file with mode: 0644]
include/linux/a.out.h
include/linux/blk.h
include/linux/busmouse.h
include/linux/fs.h
include/linux/major.h
include/linux/mount.h
include/linux/serial.h
init/main.c
kernel/exit.c
kernel/fork.c
kernel/ksyms.c
lib/inflate.c [new file with mode: 0644]
mm/filemap.c
mm/memory.c
mm/swap.c
net/netlink.c

index 7e4fe88ca0b70185b4583f1d7a99e8f49e23b3d1..03e0481bb95282ccc5145e766120ed26c6716b57 100644 (file)
@@ -9,11 +9,13 @@ Mount options are the same as for msdos partitions.
   conv=text     (Carriage return, line feed) is replaced with newline.
   conv=auto     Chooses, file by file, conv=binary or conv=text (by guessing)
 
-There is one mount option unique to HPFS.
+There are mount options unique to HPFS.
 
   case=lower   Convert file names to lower case.  [default]
   case=asis     Return file names as is, in mixed case.
 
+  nocheck      Proceed even if "Improperly stopped flag is set"
+
 Case is not significant in filename matching, like real HPFS.
 
 
index 9b31778360daef04976e96d21ab958cb5f93dc73..79a7e0f4d54bb6930e76c22ebfbd660af2e9d480 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 47
+SUBLEVEL = 48
 
 ARCH = i386
 
@@ -171,11 +171,9 @@ symlinks:
 oldconfig: symlinks
        $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
 
-xconfig: symlinks scripts/kconfig.tk
-       wish -f scripts/kconfig.tk
-
-scripts/kconfig.tk:
+xconfig: symlinks
        $(MAKE) -C scripts kconfig.tk
+       wish -f scripts/kconfig.tk
 
 config: symlinks
        $(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
index 64adf935cb2adf992d17953809019cc808386cc7..cde075032530c7d4f25ec729dba99ff91195f112 100644 (file)
@@ -229,7 +229,7 @@ void start_kernel(void)
                          envval, sizeof(envval));
        if (nbytes > 0) {
                envval[nbytes] = '\0';
-               strcpy((char*)ZERO_PGE, envval);
+               strcpy((char*)ZERO_PAGE, envval);
        }
 
        printk(" Ok\nNow booting the kernel\n");
index f71d6c57107e6b2642f660bb13f17f2e0251f163..3f863b9ad9161830eb8b62fd06e71baa2d90132a 100644 (file)
@@ -40,7 +40,7 @@ CONFIG_ST506=y
 #
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDEATAPI is not set
 # CONFIG_BLK_DEV_TRITON is not set
 # CONFIG_BLK_DEV_XD is not set
 
@@ -48,6 +48,7 @@ CONFIG_BLK_DEV_IDE=y
 # Networking options
 #
 # CONFIG_FIREWALL is not set
+# CONFIG_NET_ALIAS is not set
 CONFIG_INET=y
 # CONFIG_IP_FORWARD is not set
 # CONFIG_IP_MULTICAST is not set
@@ -166,6 +167,7 @@ CONFIG_PSMOUSE=y
 # CONFIG_MS_BUSMOUSE is not set
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
 
 #
 # Sound
index 133d654096b182bf4e2ba379386549bf9af4ffa1..d198719c4c5e3ab6054cbbeee1ff0c6500bad802 100644 (file)
@@ -427,6 +427,14 @@ static inline void common_fixup(long min_idsel, long max_idsel, long irqs_per_sl
                pcibios_write_config_byte(dev->bus->number, dev->devfn,
                                          PCI_INTERRUPT_LINE, dev->irq);
 #endif
+               /*
+                * if its a VGA, enable its BIOS ROM at C0000
+                */
+               if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+                       pcibios_write_config_dword(dev->bus->number, dev->devfn,
+                                                  PCI_ROM_ADDRESS,
+                                                  0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+               }
        }
        if (ide_base) {
                enable_ide(ide_base);
@@ -612,6 +620,14 @@ static inline void avanti_and_noname_fixup(void)
                if (pirq < 0) {
                        continue;
                }
+               /*
+                * if its a VGA, enable its BIOS ROM at C0000
+                */
+               if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+                       pcibios_write_config_dword(dev->bus->number, dev->devfn,
+                                                  PCI_ROM_ADDRESS,
+                                                  0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+               }
                if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
                        continue; /* for now, displays get no IRQ */
                }
@@ -620,7 +636,6 @@ static inline void avanti_and_noname_fixup(void)
                /* must set the PCI IRQs to level triggered */
                /* assume they are all >= 8 */
                level_bits |= (1 << (dev->irq - 8));
-               outb(level_bits, 0x4d1);
 
 #if PCI_MODIFY
                /* tell the device: */
@@ -628,6 +643,10 @@ static inline void avanti_and_noname_fixup(void)
                                          PCI_INTERRUPT_LINE, dev->irq);
 #endif
        }
+       /* now, set any level-triggered IRQs */
+       if (level_bits)
+               outb(level_bits, 0x4d1);
+
 
 #if PCI_MODIFY
        {
index f911b73275d41451a6ed683260a9110f4173ff0a..22fc92a970cd58b0218dc615e89f9beb9da59974 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/config.h>      /* CONFIG_ALPHA_LCA etc */
 
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
@@ -44,7 +45,7 @@ unsigned char aux_device_present = 0xaa;
  * initialized, we need to copy things out into a more permanent
  * place.
  */
-#define PARAM                  ZERO_PGE
+#define PARAM                  ZERO_PAGE
 #define COMMAND_LINE           ((char*)(PARAM + 0x0000))
 #define COMMAND_LINE_SIZE      256
 
index 629f17eeb8ba3aef821c090c36dd60fcd52679bd..25261759c6ba1e0f25333cc08c3de1255c54496f 100644 (file)
 #include <asm/pgtable.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void tbi(unsigned long type, unsigned long arg);
-#define tbisi(x) tbi(1,(x))
-#define tbisd(x) tbi(2,(x))
-#define tbis(x)  tbi(3,(x))
 
 /*
  * This routine handles page faults.  It determines the address,
index 3fb99e7f559320669b46128dbf21099b358f98d0..ebb3edcb60360d739d99a5f91463eed28260f768 100644 (file)
@@ -50,12 +50,6 @@ pte_t __bad_page(void)
        return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
 }
 
-unsigned long __zero_page(void)
-{
-       memset((void *) ZERO_PGE, 0, PAGE_SIZE);
-       return (unsigned long) ZERO_PGE;
-}
-
 void show_mem(void)
 {
        int i,free = 0,total = 0,reserved = 0;
@@ -131,7 +125,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 
        /* unmap the console stuff: we don't need it, and we don't want it */
        /* Also set up the real kernel PCB while we're at it.. */
-       memset((void *) ZERO_PGE, 0, PAGE_SIZE);
+       memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
        memset(swapper_pg_dir, 0, PAGE_SIZE);
        newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
        pgd_val(swapper_pg_dir[1023]) = (newptbr << 32) | pgprot_val(PAGE_KERNEL);
index 91407065c974664a63218edcb17518c835f5f4e1..74bc60b2db7576f6c63b57b63e5b3f8cef4ea2d7 100644 (file)
@@ -7,7 +7,7 @@
 HEAD = head.o
 SYSTEM = $(TOPDIR)/vmlinux
 
-OBJECTS = $(HEAD) inflate.o unzip.o misc.o
+OBJECTS = $(HEAD) misc.o
 
 CFLAGS = -O2 -DSTDC_HEADERS
 
diff --git a/arch/i386/boot/compressed/Makefile.debug b/arch/i386/boot/compressed/Makefile.debug
new file mode 100644 (file)
index 0000000..83714b5
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# linux/arch/i386/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+OBJECTS = misc.o 
+
+CFLAGS = -g -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall
+
+test-gzip: piggy.o $(OBJECTS)
+       $(CC) -g -o test-gzip $(OBJECTS) piggy.o
+
+clean: 
+       $(RM) inflate.o misc.o test-gzip
+
+inflate.o: inflate.c gzip.h
+
+misc.o: misc.c gzip.h
+
+
diff --git a/arch/i386/boot/compressed/crypt.h b/arch/i386/boot/compressed/crypt.h
deleted file mode 100644 (file)
index 2a4c203..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* crypt.h (dummy version) -- do not perform encryption
- * Hardly worth copyrighting :-)
- */
-
-#ifdef CRYPT
-#  undef CRYPT      /* dummy version */
-#endif
-
-#define RAND_HEAD_LEN  12  /* length of encryption random header */
-
-#define zencode
-#define zdecode
diff --git a/arch/i386/boot/compressed/gzip.h b/arch/i386/boot/compressed/gzip.h
deleted file mode 100644 (file)
index 2f738b9..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/* gzip.h -- common declarations for all gzip modules
- * Copyright (C) 1992-1993 Jean-loup Gailly.
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-#if defined(__STDC__) || defined(PROTO)
-#  define OF(args)  args
-#else
-#  define OF(args)  ()
-#endif
-
-#ifdef __STDC__
-   typedef void *voidp;
-#else
-   typedef char *voidp;
-#endif
-
-/* I don't like nested includes, but the string functions are used too often */
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#  include <string.h>
-#  define memzero(s, n)     memset ((s), 0, (n))
-#else
-#  include <strings.h>
-#  define strchr            index 
-#  define strrchr           rindex
-#  define memcpy(d, s, n)   bcopy((s), (d), (n)) 
-#  define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 
-#  define memzero(s, n)     bzero((s), (n))
-#endif
-
-#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
-#  include <memory.h>
-#endif
-
-#ifndef RETSIGTYPE
-#  define RETSIGTYPE void
-#endif
-
-#define local static
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-/* Return codes from gzip */
-#define OK      0
-#define ERROR   1
-#define WARNING 2
-
-/* Compression methods (see algorithm.doc) */
-#define STORED     0
-#define COMPRESSED 1
-#define PACKED     2
-/* methods 3 to 7 reserved */
-#define DEFLATED   8
-extern int method;         /* compression method */
-
-/* To save memory for 16 bit systems, some arrays are overlayed between
- * the various modules:
- * deflate:  prev+head   window      d_buf  l_buf  outbuf
- * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
- * inflate:              window             inbuf
- * unpack:               window             inbuf
- * For compression, input is done in window[]. For decompression, output
- * is done in window except for unlzw.
- */
-
-#ifndef        INBUFSIZ
-#  define INBUFSIZ  0x8000  /* input buffer size */
-#endif
-#define INBUF_EXTRA  64     /* required by unlzw() */
-
-#ifndef        OUTBUFSIZ
-#  define OUTBUFSIZ  16384  /* output buffer size */
-#endif
-#define OUTBUF_EXTRA 2048   /* required by unlzw() */
-
-#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
-
-#ifdef DYN_ALLOC
-#  define EXTERN(type, array)  extern type * near array
-#  define DECLARE(type, array, size)  type * near array
-#  define ALLOC(type, array, size) { \
-      array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
-      if (array == NULL) error("insufficient memory"); \
-   }
-#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
-#else
-#  define EXTERN(type, array)  extern type array[]
-#  define DECLARE(type, array, size)  type array[size]
-#  define ALLOC(type, array, size)
-#  define FREE(array)
-#endif
-
-EXTERN(uch, inbuf);          /* input buffer */
-EXTERN(uch, outbuf);         /* output buffer */
-EXTERN(ush, d_buf);          /* buffer for distances, see trees.c */
-EXTERN(uch, window);         /* Sliding window and suffix table (unlzw) */
-#define tab_suffix window
-#ifndef MAXSEG_64K
-#  define tab_prefix prev    /* hash link (see deflate.c) */
-#  define head (prev+WSIZE)  /* hash head (see deflate.c) */
-   EXTERN(ush, tab_prefix);  /* prefix code (see unlzw.c) */
-#else
-#  define tab_prefix0 prev
-#  define head tab_prefix1
-   EXTERN(ush, tab_prefix0); /* prefix for even codes */
-   EXTERN(ush, tab_prefix1); /* prefix for odd  codes */
-#endif
-
-extern unsigned insize; /* valid bytes in inbuf */
-extern unsigned inptr;  /* index of next byte to be processed in inbuf */
-extern unsigned outcnt; /* bytes in output buffer */
-
-extern long bytes_in;   /* number of input bytes */
-extern long bytes_out;  /* number of output bytes */
-extern long overhead;   /* number of bytes in gzip header */
-
-#define isize bytes_in
-/* for compatibility with old zip sources (to be cleaned) */
-
-extern int  ifd;        /* input file descriptor */
-extern int  ofd;        /* output file descriptor */
-extern char ifname[];   /* input filename or "stdin" */
-extern char ofname[];   /* output filename or "stdout" */
-
-extern ulg time_stamp;  /* original time stamp (modification time) */
-extern long ifile_size; /* input file size, -1 for devices (debug only) */
-
-extern int exit_code;   /* program exit code */
-
-typedef int file_t;     /* Do not use stdio */
-#define NO_FILE  (-1)   /* in memory compression */
-
-
-#define        GZIP_MAGIC     "\037\213" /* Magic header for gzip files, 1F 8B */
-#define        OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
-#define        PKZIP_MAGIC  "PK\003\004" /* Magic header for pkzip files */
-#define        PACK_MAGIC     "\037\036" /* Magic header for packed files */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-/* internal file attribute */
-#define UNKNOWN (-1)
-#define BINARY  0
-#define ASCII   1
-
-#ifndef WSIZE
-#  define WSIZE 0x8000     /* window size--must be a power of two, and */
-#endif                     /*  at least 32K for zip's deflate method */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
-extern int decrypt;        /* flag to turn on decryption */
-extern int save_orig_name; /* set if original name must be saved */
-extern int verbose;        /* be verbose (-v) */
-extern int level;          /* compression level */
-extern int test;           /* check .z file integrity */
-extern int to_stdout;      /* output to stdout (-c) */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* put_byte is used for the compressed output, put_char for the
- * uncompressed output. However unlzw() uses window for its
- * suffix table instead of its output buffer, so it does not use put_char.
- * (to be cleaned up).
- */
-#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
-   flush_outbuf();}
-#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
-   flush_window();}
-
-/* Output a 16 bit value, lsb first */
-#define put_short(w) \
-{ if (outcnt < OUTBUFSIZ-2) { \
-    outbuf[outcnt++] = (uch) ((w) & 0xff); \
-    outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
-  } else { \
-    put_byte((uch)((w) & 0xff)); \
-    put_byte((uch)((ush)(w) >> 8)); \
-  } \
-}
-
-/* Output a 32 bit value to the bit stream, lsb first */
-#define put_long(n) { \
-    put_short((n) & 0xffff); \
-    put_short(((ulg)(n)) >> 16); \
-}
-
-#define seekable()    0  /* force sequential output */
-#define translate_eol 0  /* no option -a yet */
-
-#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    /* force to lower case */
-
-/* Macros for getting two-byte and four-byte header values */
-#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
-#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-       /* in zip.c: */
-extern void zip    OF((int in, int out));
-extern int file_read  OF((char *buf,  unsigned size));
-
-       /* in unzip.c */
-extern void unzip        OF((int in, int out));
-extern int check_zipfile OF((int in));
-
-       /* in unpack.c */
-extern void unpack        OF((int in, int out));
-
-       /* in gzip.c */
-RETSIGTYPE abort_gzip   OF((void));
-
-        /* in deflate.c */
-void lm_init OF((int pack_level, ush *flags));
-ulg  deflate OF((void));
-
-        /* in trees.c */
-void ct_init     OF((ush *attr, int *method));
-int  ct_tally    OF((int dist, int lc));
-ulg  flush_block OF((char *buf, ulg stored_len, int eof));
-
-        /* in bits.c */
-void     bi_init    OF((file_t zipfile));
-void     send_bits  OF((int value, int length));
-unsigned bi_reverse OF((unsigned value, int length));
-void     bi_windup  OF((void));
-void     copy_block OF((char *buf, unsigned len, int header));
-extern   int (*read_buf) OF((char *buf, unsigned size));
-
-       /* in util.c: */
-extern ulg  updcrc        OF((uch *s, unsigned n));
-extern void clear_bufs    OF((void));
-extern int  fill_inbuf    OF((void));
-extern void flush_outbuf  OF((void));
-extern void flush_window  OF((void));
-extern char *strlwr       OF((char *s));
-extern char *basename     OF((char *fname));
-extern char *add_envopt   OF((int *argcp, char ***argvp, char *env));
-extern void error         OF((char *m));
-extern void warn          OF((char *a, char *b));
-extern void read_error    OF((void));
-extern void write_error   OF((void));
-extern void display_ratio OF((long num, long den));
-extern voidp xmalloc      OF((unsigned int size));
-
-       /* in inflate.c */
-extern int inflate OF((void));
diff --git a/arch/i386/boot/compressed/inflate.c b/arch/i386/boot/compressed/inflate.c
deleted file mode 100644 (file)
index 848fef6..0000000
+++ /dev/null
@@ -1,810 +0,0 @@
-#define DEBG(x)
-#define DEBG1(x)
-/* inflate.c -- Not copyrighted 1992 by Mark Adler
-   version c10p1, 10 January 1993 */
-
-/* 
- * Adapted for booting Linux by Hannu Savolainen 1993
- * based on gzip-1.0.3 
- */
-
-#ifndef lint
-static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
-#endif
-
-#include "gzip.h"
-#define slide window
-
-#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
-#  include <sys/types.h>
-#  include <stdlib.h>
-#endif
-
-struct huft {
-  uch e;                /* number of extra bits or operation */
-  uch b;                /* number of bits in this code or subcode */
-  union {
-    ush n;              /* literal, length base, or distance base */
-    struct huft *t;     /* pointer to next level of table */
-  } v;
-};
-
-
-/* Function prototypes */
-int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
-                   struct huft **, int *));
-int huft_free OF((struct huft *));
-int inflate_codes OF((struct huft *, struct huft *, int, int));
-int inflate_stored OF((void));
-int inflate_fixed OF((void));
-int inflate_dynamic OF((void));
-int inflate_block OF((int *));
-int inflate OF((void));
-
-
-#define wp outcnt
-#define flush_output(w) (wp=(w),flush_window())
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-static unsigned border[] = {    /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-static ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* note: see note #13 above about the 258 in this list. */
-static ush cplext[] = {         /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
-static ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-static ush cpdext[] = {         /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-
-ulg bb;                         /* bit buffer */
-unsigned bk;                    /* bits in bit buffer */
-
-ush mask_bits[] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-#ifdef CRYPT
-  uch cc;
-#  define NEXTBYTE() \
-     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
-#else
-#  define NEXTBYTE()  (uch)get_byte()
-#endif
-#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
-#define DUMPBITS(n) {b>>=(n);k-=(n);}
-
-int lbits = 9;          /* bits in base literal/length lookup table */
-int dbits = 6;          /* bits in base distance lookup table */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
-#define BMAX 16         /* maximum bit length of any code (16 for explode) */
-#define N_MAX 288       /* maximum number of codes in any set */
-
-
-unsigned hufts;         /* track memory usage */
-
-
-int huft_build(b, n, s, d, e, t, m)
-unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
-unsigned n;             /* number of codes (assumed <= N_MAX) */
-unsigned s;             /* number of simple-valued codes (0..s-1) */
-ush *d;                 /* list of base values for non-simple codes */
-ush *e;                 /* list of extra bits for non-simple codes */
-struct huft **t;        /* result: starting table */
-int *m;                 /* maximum lookup bits, returns actual */
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return zero on success, one if
-   the given code set is incomplete (the tables are still built in this
-   case), two if the input is invalid (all zero length codes or an
-   oversubscribed set of lengths), and three if not enough memory. */
-{
-  unsigned a;                   /* counter for codes of length k */
-  unsigned c[BMAX+1];           /* bit length count table */
-  unsigned f;                   /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register unsigned i;          /* counter, current code */
-  register unsigned j;          /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  register unsigned *p;         /* pointer into c[], b[], or v[] */
-  register struct huft *q;      /* points to current table */
-  struct huft r;                /* table entry for structure assignment */
-  struct huft *u[BMAX];         /* table stack */
-  unsigned v[N_MAX];            /* values in order of bit length */
-  register int w;               /* bits before this table == (l * h) */
-  unsigned x[BMAX+1];           /* bit offsets, then code stack */
-  unsigned *xp;                 /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  unsigned z;                   /* number of entries in current table */
-
-DEBG("huft1 ");
-
-  /* Generate counts for each bit length */
-  memzero(c, sizeof(c));
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (struct huft *)NULL;
-    *m = 0;
-    return 0;
-  }
-
-DEBG("huft2 ");
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((unsigned)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((unsigned)l > i)
-    l = i;
-  *m = l;
-
-DEBG("huft3 ");
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return 2;                 /* bad input: more codes than bits */
-  if ((y -= c[i]) < 0)
-    return 2;
-  c[i] += y;
-
-DEBG("huft4 ");
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-DEBG("huft5 ");
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-
-DEBG("h6 ");
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
-  q = (struct huft *)NULL;      /* ditto */
-  z = 0;                        /* ditto */
-DEBG("h6a ");
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-DEBG("h6b ");
-    a = c[k];
-    while (a--)
-    {
-DEBG("h6b1 ");
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-DEBG1("1 ");
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-DEBG1("2 ");
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          while (++j < z)       /* try smaller tables up to z bits */
-          {
-            if ((f <<= 1) <= *++xp)
-              break;            /* enough codes to use up j bits */
-            f -= *xp;           /* else deduct codes from patterns */
-          }
-        }
-DEBG1("3 ");
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate and link in new table */
-        q = (struct huft *)malloc((z + 1)*sizeof(struct huft));
-DEBG1("4 ");
-        hufts += z + 1;         /* track memory usage */
-        *t = q + 1;             /* link to list for huft_free() */
-        *(t = &(q->v.t)) = (struct huft *)NULL;
-        u[h] = ++q;             /* table starts after link */
-
-DEBG1("5 ");
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.b = (uch)l;         /* bits to dump before this table */
-          r.e = (uch)(16 + j);  /* bits in this table */
-          r.v.t = q;            /* pointer to this table */
-          j = i >> (w - l);     /* (get around Turbo C bug) */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-DEBG1("6 ");
-      }
-DEBG("h6c ");
-
-      /* set up table entry in r */
-      r.b = (uch)(k - w);
-      if (p >= v + n)
-        r.e = 99;               /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.e = (uch)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
-        r.v.n = *p++;           /* simple code is just the value */
-      }
-      else
-      {
-        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
-        r.v.n = d[*p++ - s];
-      }
-DEBG("h6d ");
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      while ((i & ((1 << w) - 1)) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-      }
-DEBG("h6e ");
-    }
-DEBG("h6f ");
-  }
-
-DEBG("huft7 ");
-
-  /* Return true (1) if we were given an incomplete table */
-  return y != 0 && g != 1;
-}
-
-
-
-int huft_free(t)
-struct huft *t;         /* table to free */
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
-   list of the tables it made, with the links in a dummy first entry of
-   each table. */
-{
-  register struct huft *p, *q;
-
-
-  /* Go through linked list, freeing from the malloced (t[-1]) address. */
-  p = t;
-  while (p != (struct huft *)NULL)
-  {
-    q = (--p)->v.t;
-    free(p);
-    p = q;
-  } 
-  return 0;
-}
-
-
-int inflate_codes(tl, td, bl, bd)
-struct huft *tl, *td;   /* literal/length and distance decoder tables */
-int bl, bd;             /* number of bits decoded by tl[] and td[] */
-/* inflate (decompress) the codes in a deflated (compressed) block.
-   Return an error code or zero if it all goes ok. */
-{
-  register unsigned e;  /* table entry flag/number of extra bits */
-  unsigned n, d;        /* length and index for copy */
-  unsigned w;           /* current window position */
-  struct huft *t;       /* pointer to table entry */
-  unsigned ml, md;      /* masks for bl and bd bits */
-  register ulg b;       /* bit buffer */
-  register unsigned k;  /* number of bits in bit buffer */
-
-
-  /* make local copies of globals */
-  b = bb;                       /* initialize bit buffer */
-  k = bk;
-  w = wp;                       /* initialize window position */
-
-  /* inflate the coded data */
-  ml = mask_bits[bl];           /* precompute masks for speed */
-  md = mask_bits[bd];
-  for (;;)                      /* do until end of block */
-  {
-    NEEDBITS((unsigned)bl)
-    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
-      do {
-        if (e == 99)
-          return 1;
-        DUMPBITS(t->b)
-        e -= 16;
-        NEEDBITS(e)
-      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
-    DUMPBITS(t->b)
-    if (e == 16)                /* then it's a literal */
-    {
-      slide[w++] = (uch)t->v.n;
-      if (w == WSIZE)
-      {
-        flush_output(w);
-        w = 0;
-      }
-    }
-    else                        /* it's an EOB or a length */
-    {
-      /* exit if end of block */
-      if (e == 15)
-        break;
-
-      /* get length of block to copy */
-      NEEDBITS(e)
-      n = t->v.n + ((unsigned)b & mask_bits[e]);
-      DUMPBITS(e);
-
-      /* decode distance of block to copy */
-      NEEDBITS((unsigned)bd)
-      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
-        do {
-          if (e == 99)
-            return 1;
-          DUMPBITS(t->b)
-          e -= 16;
-          NEEDBITS(e)
-        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
-      DUMPBITS(t->b)
-      NEEDBITS(e)
-      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
-      DUMPBITS(e)
-
-      /* do the copy */
-      do {
-        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
-#if !defined(NOMEMCPY) && !defined(DEBUG)
-        if (w - d >= e)         /* (this test assumes unsigned comparison) */
-        {
-          memcpy(slide + w, slide + d, e);
-          w += e;
-          d += e;
-        }
-        else                      /* do it slow to avoid memcpy() overlap */
-#endif /* !NOMEMCPY */
-          do {
-            slide[w++] = slide[d++];
-          } while (--e);
-        if (w == WSIZE)
-        {
-          flush_output(w);
-          w = 0;
-        }
-      } while (n);
-    }
-  }
-
-
-  /* restore the globals from the locals */
-  wp = w;                       /* restore global window pointer */
-  bb = b;                       /* restore global bit buffer */
-  bk = k;
-
-  /* done */
-  return 0;
-}
-
-
-
-int inflate_stored()
-/* "decompress" an inflated type 0 (stored) block. */
-{
-  unsigned n;           /* number of bytes in block */
-  unsigned w;           /* current window position */
-  register ulg b;       /* bit buffer */
-  register unsigned k;  /* number of bits in bit buffer */
-
-DEBG("<stor");
-
-  /* make local copies of globals */
-  b = bb;                       /* initialize bit buffer */
-  k = bk;
-  w = wp;                       /* initialize window position */
-
-
-  /* go to byte boundary */
-  n = k & 7;
-  DUMPBITS(n);
-
-
-  /* get the length and its complement */
-  NEEDBITS(16)
-  n = ((unsigned)b & 0xffff);
-  DUMPBITS(16)
-  NEEDBITS(16)
-  if (n != (unsigned)((~b) & 0xffff))
-    return 1;                   /* error in compressed data */
-  DUMPBITS(16)
-
-
-  /* read and output the compressed data */
-  while (n--)
-  {
-    NEEDBITS(8)
-    slide[w++] = (uch)b;
-    if (w == WSIZE)
-    {
-      flush_output(w);
-      w = 0;
-    }
-    DUMPBITS(8)
-  }
-
-
-  /* restore the globals from the locals */
-  wp = w;                       /* restore global window pointer */
-  bb = b;                       /* restore global bit buffer */
-  bk = k;
-
-  DEBG(">");
-  return 0;
-}
-
-
-
-int inflate_fixed()
-/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
-   either replace this with a custom decoder, or at least precompute the
-   Huffman tables. */
-{
-  int i;                /* temporary variable */
-  struct huft *tl;      /* literal/length code table */
-  struct huft *td;      /* distance code table */
-  int bl;               /* lookup bits for tl */
-  int bd;               /* lookup bits for td */
-  unsigned l[288];      /* length list for huft_build */
-
-DEBG("<fix");
-
-  /* set up literal table */
-  for (i = 0; i < 144; i++)
-    l[i] = 8;
-  for (; i < 256; i++)
-    l[i] = 9;
-  for (; i < 280; i++)
-    l[i] = 7;
-  for (; i < 288; i++)          /* make a complete, but wrong code set */
-    l[i] = 8;
-  bl = 7;
-  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
-    return i;
-
-
-  /* set up distance table */
-  for (i = 0; i < 30; i++)      /* make an incomplete code set */
-    l[i] = 5;
-  bd = 5;
-  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
-  {
-    huft_free(tl);
-
-    DEBG(">");
-    return i;
-  }
-
-
-  /* decompress until an end-of-block code */
-  if (inflate_codes(tl, td, bl, bd))
-    return 1;
-
-
-  /* free the decoding tables, return */
-  huft_free(tl);
-  huft_free(td);
-  return 0;
-}
-
-
-
-int inflate_dynamic()
-/* decompress an inflated type 2 (dynamic Huffman codes) block. */
-{
-  int i;                /* temporary variables */
-  unsigned j;
-  unsigned l;           /* last length */
-  unsigned m;           /* mask for bit lengths table */
-  unsigned n;           /* number of lengths to get */
-  struct huft *tl;      /* literal/length code table */
-  struct huft *td;      /* distance code table */
-  int bl;               /* lookup bits for tl */
-  int bd;               /* lookup bits for td */
-  unsigned nb;          /* number of bit length codes */
-  unsigned nl;          /* number of literal/length codes */
-  unsigned nd;          /* number of distance codes */
-#ifdef PKZIP_BUG_WORKAROUND
-  unsigned ll[288+32];  /* literal/length and distance code lengths */
-#else
-  unsigned ll[286+30];  /* literal/length and distance code lengths */
-#endif
-  register ulg b;       /* bit buffer */
-  register unsigned k;  /* number of bits in bit buffer */
-
-DEBG("<dyn");
-
-  /* make local bit buffer */
-  b = bb;
-  k = bk;
-
-
-  /* read in table lengths */
-  NEEDBITS(5)
-  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
-  DUMPBITS(5)
-  NEEDBITS(5)
-  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
-  DUMPBITS(5)
-  NEEDBITS(4)
-  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
-  DUMPBITS(4)
-#ifdef PKZIP_BUG_WORKAROUND
-  if (nl > 288 || nd > 32)
-#else
-  if (nl > 286 || nd > 30)
-#endif
-    return 1;                   /* bad lengths */
-
-DEBG("dyn1 ");
-
-  /* read in bit-length-code lengths */
-  for (j = 0; j < nb; j++)
-  {
-    NEEDBITS(3)
-    ll[border[j]] = (unsigned)b & 7;
-    DUMPBITS(3)
-  }
-  for (; j < 19; j++)
-    ll[border[j]] = 0;
-
-DEBG("dyn2 ");
-
-  /* build decoding table for trees--single level, 7 bit lookup */
-  bl = 7;
-  if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
-  {
-    if (i == 1)
-      huft_free(tl);
-    return i;                   /* incomplete code set */
-  }
-
-DEBG("dyn3 ");
-
-  /* read in literal and distance code lengths */
-  n = nl + nd;
-  m = mask_bits[bl];
-  i = l = 0;
-  while ((unsigned)i < n)
-  {
-    NEEDBITS((unsigned)bl)
-    j = (td = tl + ((unsigned)b & m))->b;
-    DUMPBITS(j)
-    j = td->v.n;
-    if (j < 16)                 /* length of code in bits (0..15) */
-      ll[i++] = l = j;          /* save last length in l */
-    else if (j == 16)           /* repeat last length 3 to 6 times */
-    {
-      NEEDBITS(2)
-      j = 3 + ((unsigned)b & 3);
-      DUMPBITS(2)
-      if ((unsigned)i + j > n)
-        return 1;
-      while (j--)
-        ll[i++] = l;
-    }
-    else if (j == 17)           /* 3 to 10 zero length codes */
-    {
-      NEEDBITS(3)
-      j = 3 + ((unsigned)b & 7);
-      DUMPBITS(3)
-      if ((unsigned)i + j > n)
-        return 1;
-      while (j--)
-        ll[i++] = 0;
-      l = 0;
-    }
-    else                        /* j == 18: 11 to 138 zero length codes */
-    {
-      NEEDBITS(7)
-      j = 11 + ((unsigned)b & 0x7f);
-      DUMPBITS(7)
-      if ((unsigned)i + j > n)
-        return 1;
-      while (j--)
-        ll[i++] = 0;
-      l = 0;
-    }
-  }
-
-DEBG("dyn4 ");
-
-  /* free decoding table for trees */
-  huft_free(tl);
-
-DEBG("dyn5 ");
-
-  /* restore the global bit buffer */
-  bb = b;
-  bk = k;
-
-DEBG("dyn5a ");
-
-  /* build the decoding tables for literal/length and distance codes */
-  bl = lbits;
-  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
-  {
-DEBG("dyn5b ");
-    if (i == 1) {
-      error(" incomplete literal tree\n");
-      huft_free(tl);
-    }
-    return i;                   /* incomplete code set */
-  }
-DEBG("dyn5c ");
-  bd = dbits;
-  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
-  {
-DEBG("dyn5d ");
-    if (i == 1) {
-      error(" incomplete distance tree\n");
-#ifdef PKZIP_BUG_WORKAROUND
-      i = 0;
-    }
-#else
-      huft_free(td);
-    }
-    huft_free(tl);
-    return i;                   /* incomplete code set */
-#endif
-  }
-
-DEBG("dyn6 ");
-
-  /* decompress until an end-of-block code */
-  if (inflate_codes(tl, td, bl, bd))
-    return 1;
-
-DEBG("dyn7 ");
-
-  /* free the decoding tables, return */
-  huft_free(tl);
-  huft_free(td);
-
-  DEBG(">");
-  return 0;
-}
-
-
-
-int inflate_block(e)
-int *e;                 /* last block flag */
-/* decompress an inflated block */
-{
-  unsigned t;           /* block type */
-  register ulg b;       /* bit buffer */
-  register unsigned k;  /* number of bits in bit buffer */
-
-  DEBG("<blk");
-
-  /* make local bit buffer */
-  b = bb;
-  k = bk;
-
-
-  /* read in last block bit */
-  NEEDBITS(1)
-  *e = (int)b & 1;
-  DUMPBITS(1)
-
-
-  /* read in block type */
-  NEEDBITS(2)
-  t = (unsigned)b & 3;
-  DUMPBITS(2)
-
-
-  /* restore the global bit buffer */
-  bb = b;
-  bk = k;
-
-  /* inflate that block type */
-  if (t == 2)
-    return inflate_dynamic();
-  if (t == 0)
-    return inflate_stored();
-  if (t == 1)
-    return inflate_fixed();
-
-  DEBG(">");
-
-  /* bad block type */
-  return 2;
-}
-
-
-
-int inflate()
-/* decompress an inflated entry */
-{
-  int e;                /* last block flag */
-  int r;                /* result code */
-  unsigned h;           /* maximum struct huft's malloc'ed */
-
-
-  /* initialize window, bit buffer */
-  wp = 0;
-  bk = 0;
-  bb = 0;
-
-
-  /* decompress until the last block */
-  h = 0;
-  do {
-    hufts = 0;
-    if ((r = inflate_block(&e)) != 0)
-      return r;
-    if (hufts > h)
-      h = hufts;
-  } while (!e);
-
-  /* Undo too much lookahead. The next read will be byte aligned so we
-   * can discard unused bits in the last meaningful byte.
-   */
-  while (bk >= 8) {
-    bk -= 8;
-    inptr--;
-  }
-
-  /* flush out slide */
-  flush_output(wp);
-
-
-  /* return success */
-#ifdef DEBUG
-  fprintf(stderr, "<%u> ", h);
-#endif /* DEBUG */
-  return 0;
-}
diff --git a/arch/i386/boot/compressed/lzw.h b/arch/i386/boot/compressed/lzw.h
deleted file mode 100644 (file)
index 4e640f5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* lzw.h -- define the lzw functions.
- * Copyright (C) 1992-1993 Jean-loup Gailly.
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-#if !defined(OF) && defined(lint)
-#  include "gzip.h"
-#endif
-
-#ifndef BITS
-#  define BITS 16
-#endif
-#define INIT_BITS 9              /* Initial number of bits per code */
-
-#define        LZW_MAGIC  "\037\235"   /* Magic header for lzw files, 1F 9D */
-
-#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
-/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
- * It's a pity that old uncompress does not check bit 0x20. That makes
- * extension of the format actually undesirable because old compress
- * would just crash on the new format instead of giving a meaningful
- * error message. It does check the number of bits, but it's more
- * helpful to say "unsupported format, get a new version" than
- * "can only handle 16 bits".
- */
-
-#define BLOCK_MODE  0x80
-/* Block compression: if table is full and compression rate is dropping,
- * clear the dictionary.
- */
-
-#define LZW_RESERVED 0x60 /* reserved bits */
-
-#define        CLEAR  256       /* flush the dictionary */
-#define FIRST  (CLEAR+1) /* first free entry */
-
-extern int maxbits;      /* max bits per code for LZW */
-extern int block_mode;   /* block compress mode -C compatible with 2.0 */
-
-extern void lzw    OF((int in, int out));
-extern void unlzw  OF((int in, int out));
index 5c49c258a610b974611a7bcbf9178e9c615fef66..6133622a4abdd313320dbf6672fbcedfe8db879a 100644 (file)
@@ -8,12 +8,68 @@
  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
  */
 
-#include "gzip.h"
-#include "lzw.h"
+#include <string.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
 
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000           /* Window size must be at least 32k, */
+                               /* and a power of two */
+
+static uch *inbuf;          /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+               
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+  
 /*
  * These are set up by the setup-routine at boot-time:
  */
@@ -42,83 +98,63 @@ struct screen_info {
 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
 #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
 
-#define EOF -1
-
-DECLARE(uch, inbuf, INBUFSIZ);
-DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
-DECLARE(uch, window, WSIZE);
-
-unsigned outcnt;
-unsigned insize;
-unsigned inptr;
-
 extern char input_data[];
 extern int input_len;
 
-int input_ptr;
-
-int method, exit_code, part_nb, last_member;
-int test = 0;
-int force = 0;
-int verbose = 1;
-long bytes_in, bytes_out;
-
-char *output_data;
-unsigned long output_ptr;
-
+static long bytes_out = 0;
+static uch *output_data;
+static unsigned long output_ptr = 0;
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+#ifndef STANDALONE_DEBUG
+static void puts(const char *);
+  
 extern int end;
-long free_mem_ptr = (long)&end;
-
-int to_stdout = 0;
-int hard_math = 0;
+static long free_mem_ptr = (long)&end;
 
-void (*work)(int inf, int outf);
-void makecrc(void);
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
 
-local int get_method(int);
+#include "../../../../lib/inflate.c"
 
-char *vidmem = (char *)0xb8000;
-int vidport;
-int lines, cols;
-
-static void puts(const char *);
-
-void *malloc(int size)
+static void *malloc(int size)
 {
        void *p;
 
        if (size <0) error("Malloc error\n");
        if (free_mem_ptr <= 0) error("Memory error\n");
 
-   while(1) {
        free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
 
        p = (void *)free_mem_ptr;
        free_mem_ptr += size;
 
-       /*
-        * The part of the compressed kernel which has already been expanded
-        * is no longer needed. Therefore we can reuse it for malloc.
-        * With bigger kernels, this is necessary.
-        */
-          
-       if (free_mem_ptr < (long)&end) {
-               if (free_mem_ptr > (long)&input_data[input_ptr])
-                       error("\nOut of memory\n");
-
-               return p;
-       }
-       if (free_mem_ptr < 0x90000)
+       if (free_mem_ptr >= 0x90000)
+               error("\nOut of memory\n");
+
        return p;
-       puts("large kernel, low 1M tight...");
-       free_mem_ptr = (long)input_data;
-       }
 }
 
-void free(void *where)
+static void free(void *where)
 {      /* Don't care */
 }
 
+static void gzip_mark(void **ptr)
+{
+       *ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+       free_mem_ptr = (long) *ptr;
+}
 static void scroll()
 {
        int i;
@@ -181,129 +217,47 @@ __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
 
        for (i=0;i<__n;i++) d[i] = s[i];
 }
-
-extern ulg crc_32_tab[];   /* crc table, defined below */
-
-/* ===========================================================================
- * Run a set of bytes through the crc shift register.  If s is a NULL
- * pointer, then initialize the crc shift register contents instead.
- * Return the current crc in either case.
- */
-ulg updcrc(s, n)
-    uch *s;                 /* pointer to bytes to pump through */
-    unsigned n;             /* number of bytes in s[] */
-{
-    register ulg c;         /* temporary variable */
-
-    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
-
-    if (s == NULL) {
-       c = 0xffffffffL;
-    } else {
-       c = crc;
-       while (n--) {
-           c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
-       }
-    }
-    crc = c;
-    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
-}
-
-/* ===========================================================================
- * Clear input and output buffers
- */
-void clear_bufs()
-{
-    outcnt = 0;
-    insize = inptr = 0;
-    bytes_in = bytes_out = 0L;
-}
+#endif
 
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
  * and at least one byte is really needed.
  */
-int fill_inbuf()
+static int fill_inbuf()
 {
-    int len, i;
-
-    /* Read as much as possible */
-    insize = 0;
-    do {
-       len = INBUFSIZ-insize;
-       if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
-        if (len == 0 || len == EOF) break;
-
-        for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
-       insize += len;
-       input_ptr += len;
-    } while (insize < INBUFSIZ);
-
-    if (insize == 0) {
-       error("unable to fill buffer\n");
-    }
-    bytes_in += (ulg)insize;
-    inptr = 1;
-    return inbuf[0];
+       if (insize != 0) {
+               error("ran out of input data\n");
+       }
+
+       inbuf = input_data;
+       insize = input_len;
+       inptr = 1;
+       return inbuf[0];
 }
 
 /* ===========================================================================
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  * (Used for the decompressed data only.)
  */
-void flush_window()
+static void flush_window()
 {
-    if (outcnt == 0) return;
-    updcrc(window, outcnt);
-
-    memcpy(&output_data[output_ptr], (char *)window, outcnt);
-
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+    
+    in = window;
+    out = &output_data[output_ptr]; 
+    for (n = 0; n < outcnt; n++) {
+           ch = *out++ = *in++;
+           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
     bytes_out += (ulg)outcnt;
     output_ptr += (ulg)outcnt;
     outcnt = 0;
 }
 
-/*
- * Code to compute the CRC-32 table. Borrowed from 
- * gzip-1.0.3/makecrc.c.
- */
-
-ulg crc_32_tab[256];
-
-void
-makecrc(void)
-{
-/* Not copyrighted 1990 Mark Adler     */
-
-  unsigned long c;      /* crc shift register */
-  unsigned long e;      /* polynomial exclusive-or pattern */
-  int i;                /* counter for all possible eight bit values */
-  int k;                /* byte being shifted into crc apparatus */
-
-  /* terms of polynomial defining this crc (except x^32): */
-  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-  /* Make exclusive-or pattern from polynomial */
-  e = 0;
-  for (i = 0; i < sizeof(p)/sizeof(int); i++)
-    e |= 1L << (31 - p[i]);
-
-  crc_32_tab[0] = 0;
-
-  for (i = 1; i < 256; i++)
-  {
-    c = 0;
-    for (k = i | 256; k != 1; k >>= 1)
-    {
-      c = c & 1 ? (c >> 1) ^ e : c >> 1;
-      if (k & 1)
-        c ^= e;
-    }
-    crc_32_tab[i] = c;
-  }
-}
-
-void error(char *x)
+static void error(char *x)
 {
        puts("\n\n");
        puts(x);
@@ -321,6 +275,34 @@ struct {
        short b;
        } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
 
+#ifdef STANDALONE_DEBUG
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+char output_buffer[1024 * 800];
+
+int
+main(argc, argv)
+       int     argc;
+       char    **argv;
+{
+       output_data = output_buffer;
+
+       makecrc();
+       puts("Uncompressing Linux...");
+       gunzip();
+       puts("done.\n");
+       return 0;
+}
+
+#else
+
 void decompress_kernel()
 {
        if (SCREEN_INFO.orig_video_mode == 7) {
@@ -337,94 +319,13 @@ void decompress_kernel()
        if (EXT_MEM_K < 1024) error("<2M of mem\n");
 
        output_data = (char *)0x100000; /* Points to 1M */
-       output_ptr = 0;
-
-       exit_code = 0;
-       test = 0;
-       input_ptr = 0;
-       part_nb = 0;
-
-       clear_bufs();
        makecrc();
-
        puts("Uncompressing Linux...");
+       gunzip();
+       puts("done.\nNow booting the kernel\n");
+}
+#endif
 
-       method = get_method(0);
-
-       work(0, 0);
 
-       puts("done.\n");
 
-       puts("Now booting the kernel\n");
-}
-
-/* ========================================================================
- * Check the magic number of the input file and update ofname if an
- * original name was given and to_stdout is not set.
- * Return the compression method, -1 for error, -2 for warning.
- * Set inptr to the offset of the next byte to be processed.
- * This function may be called repeatedly for an input file consisting
- * of several contiguous gzip'ed members.
- * IN assertions: there is at least one remaining compressed member.
- *   If the member is a zip file, it must be the only one.
- */
-local int get_method(in)
-    int in;        /* input file descriptor */
-{
-    uch flags;
-    char magic[2]; /* magic header */
-
-    magic[0] = (char)get_byte();
-    magic[1] = (char)get_byte();
-
-    method = -1;                 /* unknown yet */
-    part_nb++;                   /* number of parts in gzip file */
-    last_member = 0;
-    /* assume multiple members in gzip file except for record oriented I/O */
-
-    if (memcmp(magic, GZIP_MAGIC, 2) == 0
-        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
-
-       work = unzip;
-       method = (int)get_byte();
-       flags  = (uch)get_byte();
-       if ((flags & ENCRYPTED) != 0)
-           error("Input is encrypted\n");
-       if ((flags & CONTINUATION) != 0)
-              error("Multi part input\n");
-       if ((flags & RESERVED) != 0) {
-           error("Input has invalid flags\n");
-           exit_code = ERROR;
-           if (force <= 1) return -1;
-       }
-       (ulg)get_byte();        /* Get timestamp */
-       ((ulg)get_byte()) << 8;
-       ((ulg)get_byte()) << 16;
-       ((ulg)get_byte()) << 24;
-
-       (void)get_byte();  /* Ignore extra flags for the moment */
-       (void)get_byte();  /* Ignore OS type for the moment */
-
-       if ((flags & EXTRA_FIELD) != 0) {
-           unsigned len = (unsigned)get_byte();
-           len |= ((unsigned)get_byte())<<8;
-           while (len--) (void)get_byte();
-       }
 
-       /* Get original file name if it was truncated */
-       if ((flags & ORIG_NAME) != 0) {
-           if (to_stdout || part_nb > 1) {
-               /* Discard the old name */
-               while (get_byte() != 0) /* null */ ;
-           } else {
-           } /* to_stdout */
-       } /* orig_name */
-
-       /* Discard file comment if any */
-       if ((flags & COMMENT) != 0) {
-           while (get_byte() != 0) /* null */ ;
-       }
-    } else
-       error("unknown compression method");
-    return method;
-}
diff --git a/arch/i386/boot/compressed/unzip.c b/arch/i386/boot/compressed/unzip.c
deleted file mode 100644 (file)
index d4a6617..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/* unzip.c -- decompress files in gzip or pkzip format.
- * Copyright (C) 1992-1993 Jean-loup Gailly
- *
- * Adapted for Linux booting by Hannu Savolainen 1993
- *
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- *
- * The code in this file is derived from the file funzip.c written
- * and put in the public domain by Mark Adler.
- */
-
-/*
-   This version can extract files in gzip or pkzip format.
-   For the latter, only the first entry is extracted, and it has to be
-   either deflated or stored.
- */
-
-#ifndef lint
-static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
-#endif
-
-#include "gzip.h"
-#include "crypt.h"
-
-#include <stdio.h>
-
-/* PKZIP header definitions */
-#define LOCSIG 0x04034b50L      /* four-byte lead-in (lsb first) */
-#define LOCFLG 6                /* offset of bit flag */
-#define  CRPFLG 1               /*  bit for encrypted entry */
-#define  EXTFLG 8               /*  bit for extended local header */
-#define LOCHOW 8                /* offset of compression method */
-#define LOCTIM 10               /* file mod time (for decryption) */
-#define LOCCRC 14               /* offset of crc */
-#define LOCSIZ 18               /* offset of compressed size */
-#define LOCLEN 22               /* offset of uncompressed length */
-#define LOCFIL 26               /* offset of file name field length */
-#define LOCEXT 28               /* offset of extra field length */
-#define LOCHDR 30               /* size of local header, including sig */
-#define EXTHDR 16               /* size of extended local header, inc sig */
-
-
-/* Globals */
-
-int decrypt;      /* flag to turn on decryption */
-char *key;        /* not used--needed to link crypt.c */
-int pkzip = 0;    /* set for a pkzip file */
-int extended = 0; /* set if extended local header */
-
-/* ===========================================================================
- * Check zip file and advance inptr to the start of the compressed data.
- * Get ofname from the local header if necessary.
- */
-int check_zipfile(in)
-    int in;   /* input file descriptors */
-{
-    uch *h = inbuf + inptr; /* first local header */
-
-    /* ifd = in; */
-
-    /* Check validity of local header, and skip name and extra fields */
-    inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
-
-    if (inptr > insize || LG(h) != LOCSIG) {
-       error("input not a zip");
-    }
-    method = h[LOCHOW];
-    if (method != STORED && method != DEFLATED) {
-       error("first entry not deflated or stored--can't extract");
-    }
-
-    /* If entry encrypted, decrypt and validate encryption header */
-    if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
-       error("encrypted file\n");
-       exit_code = ERROR;
-       return -1;
-    }
-
-    /* Save flags for unzip() */
-    extended = (h[LOCFLG] & EXTFLG) != 0;
-    pkzip = 1;
-
-    /* Get ofname and time stamp from local header (to be done) */
-    return 0;
-}
-
-/* ===========================================================================
- * Unzip in to out.  This routine works on both gzip and pkzip files.
- *
- * IN assertions: the buffer inbuf contains already the beginning of
- *   the compressed data, from offsets inptr to insize-1 included.
- *   The magic header has already been checked. The output buffer is cleared.
- */
-void unzip(in, out)
-    int in, out;   /* input and output file descriptors */
-{
-    ulg orig_crc = 0;       /* original crc */
-    ulg orig_len = 0;       /* original uncompressed length */
-    int n;
-    uch buf[EXTHDR];        /* extended local header */
-
-    /* ifd = in;
-    ofd = out; */
-
-    updcrc(NULL, 0);           /* initialize crc */
-
-    if (pkzip && !extended) {  /* crc and length at the end otherwise */
-       orig_crc = LG(inbuf + LOCCRC);
-       orig_len = LG(inbuf + LOCLEN);
-    }
-
-    /* Decompress */
-    if (method == DEFLATED)  {
-
-       int res = inflate();
-
-       if (res == 3) {
-           error("out of memory");
-       } else if (res != 0) {
-           error("invalid compressed format");
-       }
-
-    } else if (pkzip && method == STORED) {
-
-       register ulg n = LG(inbuf + LOCLEN);
-
-       if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
-
-           error("length mismatch");
-       }
-       while (n--) {
-           uch c = (uch)get_byte();
-#ifdef CRYPT
-           if (decrypt) zdecode(c);
-#endif
-           if (!test) put_char(c);
-       }
-    } else {
-       error("internal error, invalid method");
-    }
-
-    /* Get the crc and original length */
-    if (!pkzip) {
-        /* crc32  (see algorithm.doc)
-        * uncompressed input size modulo 2^32
-         */
-       for (n = 0; n < 8; n++) {
-           buf[n] = (uch)get_byte(); /* may cause an error if EOF */
-       }
-       orig_crc = LG(buf);
-       orig_len = LG(buf+4);
-
-    } else if (extended) {  /* If extended header, check it */
-       /* signature - 4bytes: 0x50 0x4b 0x07 0x08
-        * CRC-32 value
-         * compressed size 4-bytes
-         * uncompressed size 4-bytes
-        */
-       for (n = 0; n < EXTHDR; n++) {
-           buf[n] = (uch)get_byte(); /* may cause an error if EOF */
-       }
-       orig_crc = LG(buf+4);
-       orig_len = LG(buf+12);
-    }
-
-    /* Validate decompression */
-    if (orig_crc != updcrc(outbuf, 0)) {
-       error("crc error");
-    }
-    if (orig_len != bytes_out) {
-       error("length error");
-    }
-
-    /* Check if there are more entries in a pkzip file */
-    if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
-           error("zip file has more than one entry");
-    }
-    extended = pkzip = 0; /* for next file */
-}
index 6450c4359095ee537f67be463bb664cde49768ca..a6d63cdcf3f4f6bc7a2099f1425694717fd65c8e 100644 (file)
@@ -62,7 +62,9 @@ struct apm_bios_info apm_bios_info;
 #endif
 
 unsigned char aux_device_present;
-extern int ramdisk_size;
+extern int rd_doload;          /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;     /* starting block # of image */
 extern int root_mountflags;
 extern int _etext, _edata, _end;
 
@@ -79,12 +81,16 @@ extern char empty_zero_page[PAGE_SIZE];
 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_SIZE (*(unsigned short *) (PARAM+0x1F8))
+#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #define COMMAND_LINE ((char *) (PARAM+2048))
 #define COMMAND_LINE_SIZE 256
 
+#define RAMDISK_IMAGE_START_MASK       0x07FF
+#define RAMDISK_PROMPT_FLAG            0x8000
+#define RAMDISK_LOAD_FLAG              0x4000  
+
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 
 void setup_arch(char **cmdline_p,
@@ -110,7 +116,9 @@ void setup_arch(char **cmdline_p,
        aux_device_present = AUX_DEVICE_INFO;
        memory_end = (1<<20) + (EXT_MEM_K<<10);
        memory_end &= PAGE_MASK;
-       ramdisk_size = RAMDISK_SIZE;
+       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #ifdef CONFIG_MAX_16M
        if (memory_end > 16*1024*1024)
                memory_end = 16*1024*1024;
index e24ac87c77a66f9f082350c6d32aaa9579efbf8b..e004c99a6dae636019edf04a2a93eab6f70b8f13 100644 (file)
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1994, 1995 by Waldorf Electronics,
-# written by Ralf Baechle
+# Copyright (C) 1994, 1995 by Ralf Baechle
 #
 
-AS             = mips-linux-as
-#ASFLAGS               = -mips3 -mcpu=r4000
-LD             = mips-linux-ld
-LINKFLAGS      = -Ttext 0xa0000000
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+prefix         = mipsel-
+oformat                = a.out-mips-little-linux
+else
+prefix         = mips-
+oformat                = a.out-mips-big-linux
+endif
+
+ifdef CONFIG_EXTRA_ELF_COMPILER
+prefix         := $(prefix)linuxelf-
+else
+prefix         := $(prefix)linux-
+endif
+
+AS             = $(prefix)as
+LD             = $(prefix)ld
+LINKFLAGS      = -N -Ttext 0x80000000
+#LINKFLAGS     = -oformat=$(oformat) -N -Ttext 0x80000000
 #HOSTCC                = gcc
-#
-# KERNELBASE is quite useless, but I need it to work
-# around a hardware bug in my Wreckstation board. Other people
-# would burn that @#!%# thing...
-#
-CC             = mips-linux-gcc -V 2.5.8 -D__KERNEL__ -I$(TOPDIR)/include
+CC             = $(prefix)gcc -D__KERNEL__ -I$(TOPDIR)/include
 CPP            = $(CC) -E $(CFLAGS)
-AR             = mips-linux-ar
-RANLIB         = mips-linux-ranlib
-STRIP          = mips-linux-strip
+AR             = $(prefix)ar
+RANLIB         = $(prefix)ranlib
+OBJCOPY                = $(prefix)objcopy
+OBJDUMP                = $(prefix)objdump
+STRIP          = $(prefix)strip
+NM             = $(prefix)nm
 
-CFLAGS := $(CFLAGS) #-pipe
+#
+# The new ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
+# code in the kernel since it only slows down the whole thing.  For the
+# old GCC these options are just the defaults.  At some point we might
+# make use of global pointer optimizations.
+#
+ifdef CONFIG_ELF_KERNEL
+CFLAGS         := $(CFLAGS) -G0 -mno-abicalls -fno-pic
+LINKFLAGS      += -T arch/mips/ld.script
+endif
 
-CFLAGS := $(CFLAGS) -DKERNELBASE=0xa0000000
+ifdef CONFIG_REMOTE_DEBUG
+CFLAGS         := $(CFLAGS) -g
+endif
 
-ifdef CONFIG_R4X00
-CFLAGS := $(CFLAGS) -Wa,-mips3 -mcpu=r4000 -D__R4000__
+ifdef CONFIG_CPU_R3000
+CFLAGS         := $(CFLAGS) -mcpu=r3000 -mips1
+#ASFLAGS               := $(ASFLAGS) -mcpu=r3000 -mips1
+endif
+ifdef CONFIG_CPU_R6000
+CFLAGS         := $(CFLAGS) -mcpu=r6000 -mips2
+#ASFLAGS               := $(ASFLAGS) -mcpu=r6000 -mips2
+endif
+ifdef CONFIG_CPU_R4X00
+CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r4400 -mips2
+#ASFLAGS               := $(ASFLAGS) -mcpu=r4400 -mips2
 endif
+ifdef CONFIG_CPU_R4600
+CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r4600 -mips2
+#ASFLAGS               := $(ASFLAGS) -mcpu=r4600 -mips2
+endif
+ifdef CONFIG_CPU_R8000
+CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
+#ASFLAGS               := $(ASFLAGS) -mcpu=r8000 -mips2
+endif
+ifdef CONFIG_CPU_R10000
+CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
+#ASFLAGS               := $(ASFLAGS) -mcpu=r8000 -mips2
+endif
+
+CFLAGS         := $(CFLAGS) -pipe
 
 HEAD := arch/mips/kernel/head.o
 
-SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm
+SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib
 ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
+LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
@@ -55,6 +101,7 @@ zdisk: vmlinux
 
 archclean:
        @$(MAKEBOOT) clean
+       $(MAKE) -C arch/$(ARCH)/kernel clean
 
 archdep:
        @$(MAKEBOOT) dep
index ad59f15123b336abd937bd509da3e397eeeed6a6..3b9891a6b893e701bc46e639be126651e4147152 100644 (file)
@@ -5,20 +5,62 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995 by  Waldorf Electronics,
-# written by Ralf Baechle
+# Copyright (C) 1995 by Ralf Baechle
 #
 
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = milo.o a.out.o
+
+#
+# Drop some uninteresting sections in the kernel.
+# This is only relevant for ELF kernels but doesn't hurt a.out
+#
+DROP_SECTIONS  = .reginfo .mdebug
+
+#
+# The new options of binutils 2.6 help to shrink object files alot.
+# This is especially usefull for booting from floppy.  Though we
+# don't yet require everyone to have binutils 2.6 installed.
+#
+OBJDUMP_VERSION =  $(word 4,$(shell $(OBJDUMP) --version))
+ifneq ($(OBJDUMP_VERSION),2.5.2)
+KEEP = kernel_entry boot_info screen_info _end
+STRIP_FLAGS = $(addprefix --keep-symbol=,$(KEEP))
+else
+STRIP_FLAGS = --discard-all
+endif
+
 #
 # Fake compressed boot
 #
+ifdef CONFIG_ELF_KERNEL
+zImage:        $(CONFIGURE) $(TOPDIR)/vmlinux
+       cp $(TOPDIR)/vmlinux zImage.tmp
+       $(STRIP) $(addprefix --remove-section=,$(DROP_SECTIONS)) \
+               --strip-symbol=blurb zImage.tmp
+       $(LD) -oformat=$(oformat) -N -e except_vec0 -Ttext=0x80000000 \
+               -o zImage zImage.tmp
+       rm -f zImage.tmp
+       $(STRIP) $(STRIP_FLAGS) zImage
+else
 zImage:        $(CONFIGURE) $(TOPDIR)/vmlinux
-       ln -fs $(TOPDIR)/vmlinux zImage
+       cp $(TOPDIR)/vmlinux $@
+       $(STRIP) $(STRIP_FLAGS) $@
+endif
 
 zdisk: zImage
-       mcopy -n $(TOPDIR)/vmlinux a:vmlinux
+       mcopy -n zImage a:vmlinux
 
 dep:
+       $(CPP) -M *.[cS] > .depend
 
 clean:
-       rm -f zImage
+       rm -f zImage zImage.tmp
+
+dummy:
+
+include $(TOPDIR)/Rules.make
index 3891b71913e2b9ac70df063bb1b4d84fa3e5c113..cddafbdae8224eb2461281658c8abc7ed23954e1 100644 (file)
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
-
+mainmenu_name "Linux Kernel Configuration"
+  
+mainmenu_option next_comment
 comment 'Machine setup'
 
-bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE y
-bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 y
-bool 'Support for DECstation' CONFIG_DECSTATION n
-
-bool 'Generate code for R4x00' CONFIG_R4X00 y
-
-comment 'General setup'
-
-bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
-bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
-if [ "$CONFIG_ST506" = "y" ]; then
-  comment 'Please see block/drivers/README.ide for help/info on IDE drives'
-  bool '   Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y
-  if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
-    bool '   Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
-  else
-    bool '   Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE n
-  fi
-  if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
-    bool '   Include support for IDE CDROM (ATAPI)' CONFIG_BLK_DEV_IDECD n
-  fi
-fi
-
-bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
-bool 'Networking support' CONFIG_NET y
-bool 'System V IPC' CONFIG_SYSVIPC n
-bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF n
+bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
+bool 'Support for DECstation' CONFIG_DECSTATION
+bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
+bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
+bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
+bool 'Support for Olivetty M700' CONFIG_OLIVETTI_M700
+if [ "$CONFIG_ACER_PICA_61" = "y" -o \
+     "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
+     "$CONFIG_OLIVETTI_M700" = "y" ]; then
+       define_bool CONFIG_MIPS_JAZZ y
+fi
+
+choice 'CPU type' \
+       "R3000 CONFIG_CPU_R3000 \
+        R6000 CONFIG_CPU_R6000 \
+        R4x00 CONFIG_CPU_R4X00 \
+        R4600 CONFIG_CPU_R4600 \
+        R8000 CONFIG_CPU_R8000 \
+        R10000 CONFIG_CPU_R10000" R4x00
+if [ "$CONFIG_CPU_R3000" = "y" -o \
+     "$CONFIG_CPU_R6000" = "y" -o \
+     "$CONFIG_CPU_R4X00" = "y" -o \
+     "$CONFIG_CPU_R4600" = "y" -o \
+     "$CONFIG_CPU_R8000" = "y" ]; then
+       define_bool CONFIG_TLB_SHUTDOWN y
+fi
+
+define_bool CONFIG_BINFMT_ELF y
+bool 'Compile the kernel into the ELF object format' CONFIG_ELF_KERNEL
+if [ "$CONFIG_ELF_KERNEL" = "y" ]; then
+  bool 'Is your ELF compiler an extra compiler' CONFIG_EXTRA_ELF_COMPILER
+fi
+bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
+bool 'Networking support' CONFIG_NET
+#bool 'PCI bios support' CONFIG_PCI
+#if [ "$CONFIG_PCI" = "y" ]; then
+#  bool '   PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE
+#fi
+bool 'System V IPC' CONFIG_SYSVIPC
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+
+source drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-comment 'Networking options'
-bool 'TCP/IP networking' CONFIG_INET y
-if [ "$CONFIG_INET" "=" "y" ]; then
-bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD y
-bool 'IP multicasting (ALPHA)' CONFIG_IP_MULTICAST n
-bool 'IP firewalling' CONFIG_IP_FIREWALL n
-bool 'IP accounting' CONFIG_IP_ACCT n
-comment '(it is safe to leave these untouched)'
-bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n
-bool 'Reverse ARP' CONFIG_INET_RARP n
-bool 'Assume subnets are local' CONFIG_INET_SNARL y
-bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
-fi
-bool 'The IPX protocol' CONFIG_IPX n
-#bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
+  source net/Config.in
 fi
 
+mainmenu_option next_comment
 comment 'SCSI support'
 
-bool 'SCSI support?' CONFIG_SCSI n
-
-if [ "$CONFIG_SCSI" = "n" ]; then
-
-comment 'Skipping SCSI configuration options...'
+tristate 'SCSI support' CONFIG_SCSI
 
-else
-
-comment 'SCSI support type (disk, tape, CDrom)'
-
-bool 'SCSI disk support' CONFIG_BLK_DEV_SD y
-bool 'SCSI tape support' CONFIG_CHR_DEV_ST y
-bool 'SCSI CDROM support' CONFIG_BLK_DEV_SR y
-bool 'SCSI generic support' CONFIG_CHR_DEV_SG y
-
-comment 'SCSI low-level drivers'
-
-bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n
-bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y
-bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n
-bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n
-bool 'EATA-DMA (DPT, NEC, ATT, Olivetti) support' CONFIG_SCSI_EATA_DMA y
-bool 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO n
-bool 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F n
-bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n
-bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n
-if [ "$CONFIG_PCI" = "y" ]; then
-  bool 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx n
-fi
-bool 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 n
-bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n
-bool 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC n
-bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n
-bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
-bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
-bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
-#bool 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA n
-#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
+if [ "$CONFIG_SCSI" != "n" ]; then
+  source drivers/scsi/Config.in
 fi
 
-
 if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device support'
 
-comment 'Network device support'
-
-bool 'Network device support?' CONFIG_NETDEVICES n
-if [ "$CONFIG_NETDEVICES" = "n" ]; then
-
-comment 'Skipping network driver configuration options...'
-
-else
-bool 'Dummy net driver support' CONFIG_DUMMY n
-bool 'SLIP (serial line) support' CONFIG_SLIP n
-if [ "$CONFIG_SLIP" = "y" ]; then
-  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-#  bool ' SLIP debugging on' SL_DUMP y
-fi
-bool 'PPP (point-to-point) support' CONFIG_PPP n
-bool 'PLIP (parallel port) support' CONFIG_PLIP n
-bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
-bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA n
-bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC y
-if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
-       bool 'WD80*3 support' CONFIG_WD80x3 y
-       bool 'SMC Ultra support' CONFIG_ULTRA n
-fi
-bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE n
-bool '3COM cards' CONFIG_NET_VENDOR_3COM y
-if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
-       bool '3c501 support' CONFIG_EL1 n
-       bool '3c503 support' CONFIG_EL2 n
-       if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-               bool '3c505 support' CONFIG_ELPLUS n
-               bool '3c507 support' CONFIG_EL16 n
-       fi
-       bool '3c509/3c579 support' CONFIG_EL3 n
-fi
-bool 'Other ISA cards' CONFIG_NET_ISA n
-if [ "$CONFIG_NET_ISA" = "y" ]; then
-       bool 'Cabletron E21xx support' CONFIG_E2100 n
-       bool 'DEPCA support' CONFIG_DEPCA n
-       bool 'EtherWorks 3 support' CONFIG_EWRK3 n
-       if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-               bool 'Arcnet support' CONFIG_ARCNET n
-               bool 'AT1700 support' CONFIG_AT1700 n
-#              bool 'EtherExpressPro support' CONFIG_EEXPRESS_PRO n
-               bool 'EtherExpress support' CONFIG_EEXPRESS n
-               bool 'NI5210 support' CONFIG_NI52 n
-               bool 'NI6510 support' CONFIG_NI65 n
-       fi
-       bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n
-       bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n
-       bool 'NE2000/NE1000 support' CONFIG_NE2000 y
-       bool 'SK_G16 support' CONFIG_SK_G16 n
-fi
-bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n
-if [ "$CONFIG_NET_EISA" = "y" ]; then
-       if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-               bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
-       fi
-       bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n
-#      bool 'DEC 21040 PCI support' CONFIG_DEC_ELCP n
-#      bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100 n
-#      bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32 n
-       bool 'Zenith Z-Note support' CONFIG_ZNET y
-fi
-bool 'Pocket and portable adaptors' CONFIG_NET_POCKET n
-if [ "$CONFIG_NET_POCKET" = "y" ]; then
-       bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
-       bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
-       bool 'D-Link DE620 pocket adaptor support' CONFIG_DE620 n
-#      bool 'Silicom pocket adaptor support' CONFIG_SILICOM_PEA n
-#      bool 'WaveLAN PCMCIA support' CONFIG_WaveLAN n
-#      bool '3 Com 3c589 PCMCIA support' CONFIG_3C589 n
-fi
-fi
-fi
-
-comment 'CD-ROM drivers'
-
-bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n
-bool 'Mitsumi CDROM driver support' CONFIG_MCD n
-bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
-if [ "$CONFIG_SBPCD" = "y" ]; then
-  bool 'Matsushita/Panasonic second CDROM controller support' CONFIG_SBPCD2 n
-  if [ "$CONFIG_SBPCD2" = "y" ]; then
-    bool 'Matsushita/Panasonic third CDROM controller support' CONFIG_SBPCD3 n
-    if [ "$CONFIG_SBPCD3" = "y" ]; then
-      bool 'Matsushita/Panasonic fourth CDROM controller support' CONFIG_SBPCD4 n
-    fi
+  bool 'Network device support' CONFIG_NETDEVICES
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    source drivers/net/Config.in
   fi
 fi
 
-comment 'Filesystems'
-
-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 'xiafs filesystem support' CONFIG_XIA_FS n
-bool 'msdos fs support' CONFIG_MSDOS_FS n
-if [ "$CONFIG_MSDOS_FS" = "y" ]; then
-bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n
-fi
-bool '/proc filesystem support' CONFIG_PROC_FS n
-if [ "$CONFIG_INET" = "y" ]; then
-bool 'NFS filesystem support' CONFIG_NFS_FS y
-fi
-if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
-       bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y
-else
-       bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
-fi
-bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
-bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
-
-comment 'character devices'
+mainmenu_option next_comment
+comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
-bool 'Cyclades async mux support' CONFIG_CYCLADES n
-bool 'Parallel printer support' CONFIG_PRINTER n
-bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
-bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE n
-if [ "$CONFIG_PSMOUSE" = "y" ]; then
-bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE n
+bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+  source drivers/cdrom/Config.in
 fi
-bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
-bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-  
-bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
-if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
-bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF n
-if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
 
-comment '>>> Edit configuration parameters in ./include/linux/tpqic02.h!'
+source fs/Config.in
 
-else
-
-comment '>>> Setting runtime QIC-02 configuration is done with qic02conf'
-comment '>>> Which is available from ftp://ftp.funet.fi/pub/OS/Linux/BETA/QIC-02/'
-
-fi
-fi
-
-bool 'QIC-117 tape support' CONFIG_FTAPE n
-if [ "$CONFIG_FTAPE" = "y" ]; then
-int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
-fi
+source drivers/char/Config.in
+bool 'Standard serial device support' CONFIG_SERIAL n
 
+mainmenu_option next_comment
 comment 'Sound'
 
-bool 'Sound card support' CONFIG_SOUND n
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+  source drivers/sound/Config.in
+fi
 
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
-bool 'Kernel profiling support' CONFIG_PROFILE n
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
-if [ "$CONFIG_SCSI" = "y" ]; then
-bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
-fi
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
new file mode 100644 (file)
index 0000000..aba2789
--- /dev/null
@@ -0,0 +1,87 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Machine setup
+#
+CONFIG_ACER_PICA_61=y
+# CONFIG_DECSTATION is not set
+# CONFIG_DESKSTATION_RPC44 is not set
+# CONFIG_DESKSTATION_TYNE is not set
+# CONFIG_MIPS_MAGNUM_3000 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
+CONFIG_MIPS_JAZZ=y
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4600 is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_TLB_SHUTDOWN=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_ELF_KERNEL is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_NET is not set
+# CONFIG_SYSVIPC is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODVERSIONS is not set
+
+#
+# block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_ST506 is not set
+# CONFIG_BLK_DEV_XD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Filesystems
+#
+# CONFIG_MINIX_FS is not set
+# CONFIG_EXT_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_XIA_FS is not set
+# CONFIG_MSDOS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_SMB_FS is not set
+
+#
+# character devices
+#
+# CONFIG_CYCLADES is not set
+# CONFIG_STALDRV is not set
+# CONFIG_PRINTER is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_SERIAL is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILE is not set
index 27c258e9e40d503c9843f5f67f1df4813a7e863f..29368b0d32022f74d41f1302b375a0b932bdcb4b 100644 (file)
 #
-# Makefile for the linux kernel.
+# Makefile for the Linux/MIPS kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-# Note 2! The CFLAGS definitions are now in the main makefile...
 
 .S.s:
-       $(CPP) $(CFLAGS) -D__ASSEMBLY__ -traditional $< -o $*.s
+       $(CPP) $(CFLAGS) $< -o $*.s
 .S.o:
-       $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+       $(CC) $(CFLAGS) -c $< -o $*.o
 
+all:   kernel.o head.o
 EXTRA_ASFLAGS = -mips3 -mcpu=r4000
-OBJS  = process.o signal.o entry.o traps.o irq.o ptrace.o cache.o resume.o \
-       ioport.o setup.o bios32.o tynedma.o
+O_TARGET := kernel.o
+O_OBJS := process.o signal.o entry.o traps.o irq.o ptrace.o vm86.o ioport.o \
+       setup.o syscall.o sysmips.o time.o bios32.o ipc.o
 
-all: kernel.o head.o
+#
+# Kernel debugging
+#
+ifdef CONFIG_REMOTE_DEBUG
+OBJS += gdb-low.o gdb-stub.o 
+endif
+
+#
+# Board specific code
+#
+ifdef CONFIG_MIPS_JAZZ
+O_OBJS += jazzdma.o jazz-c.o
+endif
+
+ifdef CONFIG_ACER_PICA_61
+O_OBJS += pica.o
+endif
+
+ifdef CONFIG_DESKSTATION_TYNE
+O_OBJS += tyne.o tyne-c.o
+endif
 
-cache.o: cache.s
+ifdef CONFIG_MIPS_MAGNUM_4000
+O_OBJS += magnum4000.o
+endif
 
-cache.s: cache.S $(TOPDIR)/include/asm/mipsconfig.h \
-       $(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/segment.h
+#
+# CPU model specific code
+#
+ifdef CONFIG_CPU_R2000
+O_OBJS += r3000.o
+endif
 
-entry.o: entry.s
+ifdef CONFIG_CPU_R3000
+O_OBJS += r3000.o
+endif
 
-entry.s: entry.S $(TOPDIR)/include/linux/sys.h \
-       $(TOPDIR)/include/linux/autoconf.h $(TOPDIR)/include/asm/segment.h \
-       $(TOPDIR)/include/asm/mipsregs.h $(TOPDIR)/include/asm/mipsconfig.h \
-       $(TOPDIR)/include/asm/page.h $(TOPDIR)/include/asm/stackframe.h \
-       $(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/processor.h
+ifdef CONFIG_CPU_R4X00
+O_OBJS += r4xx0.o
+endif
+
+ifdef CONFIG_CPU_R4600
+O_OBJS += r4xx0.o
+endif
+
+ifdef CONFIG_CPU_R6000
+       exit 1                  # no detailed informations about CPU yet.
+endif
+
+ifdef CONFIG_CPU_R8000
+       exit 1                  # no detailed informations about CPU yet.
+endif
+
+ifdef CONFIG_CPU_R10000
+O_OBJS += r4xx0.o
+endif
+
+#
+# Since we add the same object files to O_OBJS for different configurations.
+# O_OBJS might contain duplicate files.  We correct this by filtering out
+# duplicate files.  Just to avoid users having to know about all the
+# compatibility stuff between various boards and boards.
+#
+O_OBJS := $(sort $(O_OBJS))
+
+all: kernel.o head.o
 
-head.o: head.s
+entry.o: entry.S
 
-head.s: head.S $(TOPDIR)/include/linux/tasks.h
+head.o: head.S
 
-resume.o: resume.s
+magnum4000.o: magnum4000.S
 
-resume.s: resume.S $(TOPDIR)/include/asm/regdef.h \
-       $(TOPDIR)/include/asm/processor.h $(TOPDIR)/include/asm/mipsregs.h \
-       $(TOPDIR)/include/asm/mipsconfig.h
+pica.o: pica.S
 
-tlb.o: tlb.s
+r4xx0.o: r4xx0.S
 
-tlb.s: tlb.S $(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/mipsregs.h \
-       $(TOPDIR)/include/asm/bootinfo.h
+tyne.o: tyne.S
 
-kernel.o: $(OBJS)
-       $(LD) -r -o kernel.o $(OBJS)
-       sync
+clean:
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/mips/kernel/cache.S b/arch/mips/kernel/cache.S
deleted file mode 100644 (file)
index 8e1e7bb..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/mips/kernel/cache.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * Written by Ralf Baechle
- *
- * Flush instruction/data caches
- *
- * Parameters: a0 - starting address to flush
- *             a1 - size of area to be flushed
- *             a2 - which caches to be flushed
- *
- * FIXME:      - ignores parameters
- *             - doesn't know about second level caches
- *             - only knows how to handle the R4600
- */
-
-#include <asm/mipsconfig.h>
-#include <asm/regdef.h>
-#include <asm/segment.h>
-
-#define PAGE_SIZE      0x1000
-
-#define CACHELINES     512             /* number of cachelines    */
-
-               .set    noreorder
-               .globl  _sys_cacheflush
-               .text
-_sys_cacheflush:
-               /*
-                * Writeback/invalidate the data cache
-                */
-               li      t0,KSEG0
-               li      t1,CACHELINES
-1:             cache   1,0(t0)
-               cache   1,32(t0)
-               cache   1,64(t0)
-               cache   1,96(t0)
-               cache   1,128(t0)
-               cache   1,160(t0)
-               cache   1,192(t0)
-               cache   1,224(t0)
-               cache   1,256(t0)
-               cache   1,288(t0)
-               cache   1,320(t0)
-               cache   1,352(t0)
-               cache   1,384(t0)
-               cache   1,416(t0)
-               cache   1,448(t0)
-               cache   1,480(t0)
-               subu    t1,t1,1
-               bnez    t1,1b
-               addiu   t0,t0,512                       # delay slot
-
-               /*
-                * Flush the instruction cache
-                */
-               lui     t0,0x8000
-               li      t1,CACHELINES
-1:             cache   0,0(t0) 
-               cache   0,32(t0)
-               cache   0,64(t0)
-               cache   0,96(t0)
-               cache   0,128(t0)
-               cache   0,160(t0)
-               cache   0,192(t0)
-               cache   0,224(t0)
-               cache   0,256(t0)
-               cache   0,288(t0)
-               cache   0,320(t0)
-               cache   0,352(t0)
-               cache   0,384(t0)
-               cache   0,416(t0)
-               cache   0,448(t0)
-               cache   0,480(t0)
-               subu    t1,t1,1
-               bnez    t1,1b
-               addiu   t0,t0,512                       # delay slot
-
-               j       ra
-               nop
index f8b981a2ce7b1956376b0eb66250e9f1e1825926..4efb65b5da50c7c69fd71614471b5879e93c9bea 100644 (file)
@@ -1,25 +1,31 @@
 /*
- * arch/mips/kernel/entry.S
+ * Low level exception handling
  *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * written by Ralf Baechle
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
 
 /*
  * entry.S contains the system-call and fault low-level handling routines.
  * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
+ * and faults that can result in a task-switch. The ISA dependend TLB
+ * code is in arch/mips/kernel/<cputype>.S
  */
-
 #include <linux/sys.h>
-#include <linux/autoconf.h>
+
+#include <asm/asm.h>
+#include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/stackframe.h>
-#include <asm/regdef.h>
 #include <asm/processor.h>
+#include <asm/unistd.h>
 
 /*
  * These are offsets into the task-struct.
@@ -30,944 +36,276 @@ priority  =  8
 signal         = 12
 blocked                = 16
 flags          = 20
-errno          = 24                    #/* MIPS OK */
-exec_domain    = 60                    #/* ??? */
-
-ENOSYS         = 38
+errno          = 24
+exec_domain    = 60
 
-               .globl  ret_from_sys_call
-               .globl  _sys_call_table
+#ifdef __SMP__
+#error "Fix this for SMP"
+#else
+#define current current_set
+#endif
 
+/*
+ * Heia ...  The %lo, %hi and %HI stuff is too strong for the ELF assembler
+ * and the ABI to cope with ...
+ */
                .text
                .set    noreorder
                .align 4
 handle_bottom_half:
-               /*
-                * If your assembler breaks on the next line it's
-                * time to update!
-                */
-               lui     s0,%hi(_intr_count)
-               lw      s1,%lo(_intr_count)(s0)
-               mfc0    s3,CP0_STATUS                   # Enable IRQs
+               lui     s0,%hi(intr_count)
+               lw      s1,%lo(intr_count)(s0)
+               mfc0    s3,CP0_STATUS           # Enable IRQs
                addiu   s2,s1,1
-               sw      s2,%lo(_intr_count)(s0)
+               sw      s2,%lo(intr_count)(s0)
                ori     t0,s3,0x1f
-               xori    t0,t0,0x1e
-               jal     _do_bottom_half
-               mtc0    t0,CP0_STATUS                   # delay slot
-               mtc0    s3,CP0_STATUS                   # Restore old IRQ state
-               j       9f
-               sw      s1,%lo(_intr_count)(s0)         # delay slot
-
-               .set    reorder
-reschedule:
-               la      ra,ret_from_sys_call
-               j       _schedule
-               nop
-
-               .align  5
-               .globl  _handle_sys
-_handle_sys:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               .set    at
-               STI
-               /*
-                * Compute return address. For now we assume that syscalls never
-                * appear in branch delay slots. For the Linux/MIPS standard
-                * libraries this assumption is always try.
-                */
-               lw      t3,FR_EPC(sp)
-               lw      s1,FR_REG2(sp)
-               li      t0,-ENOSYS
-               addiu   t3,t3,4
-               sw      t3,FR_EPC(sp)
-               li      t2,NR_syscalls
-               bge     s1,t2,ret_from_sys_call
-               sw      t0,FR_REG2(sp)          # delay slot
-               sll     s1,s1,2
-               lw      s1,_sys_call_table(s1)
-               lw      s0,_current
-
-               beqz    s1,ret_from_sys_call
-               lw      t0,flags(s0)
-               sll     t0,t0,2                 # PF_TRACESYS
-               bltz    t0,1f
-               sw      zero,errno(s0)          # delay slot
-
-               lw      a0,FR_REG4(sp)
-               lw      a1,FR_REG5(sp)
-               lw      a2,FR_REG6(sp)
-               lw      a3,FR_REG7(sp)
-               lw      t0,FR_REG3(sp)
-               jalr    s1                      # do the real work
-               sw      t0,16(sp)               # delay slot
-
-               lw      t0,errno(s0)
-               sw      v0,FR_REG2(sp)          # save the return value
-               subu    t0,zero,t0              # t0 = -t0
-               beqz    t0,ret_from_sys_call
-               nop
-               /*
-                * Fixme: should set error flag
-                */
-               j       ret_from_sys_call
-               sw      t0,FR_REG2(sp)          # delay slot
-
-               .align  4
-1:             jal     _syscall_trace
-               nop                             # delay slot
-
-               lw      a0,FR_REG4(sp)
-               lw      a1,FR_REG5(sp)
-               lw      a2,FR_REG6(sp)
-               lw      a3,FR_REG7(sp)
-               lw      t0,FR_REG3(sp)
-               jalr    s1                      # do the real work
-               sw      t0,16(sp)               # delay slot
+               xori    t0,0x1e
+               jal     do_bottom_half
+               mtc0    t0,CP0_STATUS           # delay slot
+               mtc0    s3,CP0_STATUS           # Restore old IRQ state
+               b       9f
+               sw      s1,%lo(intr_count)(s0)  # delay slot
 
-               lw      t0,errno(s0)
-               sw      v0,FR_REG2(sp)          # save the return value
-               subu    t0,zero,t0
-               beqz    t0,1f
+reschedule:    jal     schedule 
                nop                             # delay slot
-               sw      t1,FR_REG2(sp)
-               /*
-                * Fixme: should set error flag
-                */
-1:             jal     _syscall_trace
-               nop
+EXPORT(ret_from_sys_call)
+               lw      t0,intr_count           # bottom half
+               bnez    t0,return
 
-               .align  4
-ret_from_sys_call:
-               lw      t0,_intr_count          # bottom half
-               bnez    t0,2f
-9:
-               lw      t0,_bh_mask             # delay slot
-               lw      t1,_bh_active           # unused delay slot
+9:             lw      t0,bh_mask              # delay slot
+               lw      t1,bh_active            # unused delay slot
                and     t0,t1
                bnez    t0,handle_bottom_half
 
-               lw      t0,FR_STATUS(sp)        # returning to supervisor ?
+               lw      t0,FR_STATUS(sp)        # returning to kernel mode?
                andi    t1,t0,0x10
-               beqz    t1,2f
+               beqz    t1,return               # -> yes
 
                mfc0    t0,CP0_STATUS           # delay slot
-               lw      t1,_need_resched
+               lw      t1,need_resched
                ori     t0,0x1f                 # enable irqs
                xori    t0,0x1e
                bnez    t1,reschedule
                mtc0    t0,CP0_STATUS           # delay slot
 
-               lw      s0,_current
-               lw      t0,_task
-               lw      t1,state(s0)            # state
-               beq     s0,t0,2f                # task[0] cannot have signals
-               lw      t0,counter(s0)          # counter
-               bnez    t1,reschedule           # state == 0 ?
+               lw      s0,current
+               lw      t0,task
                lw      a0,blocked(s0)
+               beq     s0,t0,return            # task[0] cannot have signals
                                                # save blocked in a0 for
                                                # signal handling
-               beqz    t0,reschedule           # counter == 0 ?
                lw      t0,signal(s0)
                nor     t1,zero,a0
                and     t1,t0,t1
-               beqz    t1,skip_signal_return
+               beqz    t1,return
                nop
 
-               jal     _do_signal
+               jal     do_signal
                move    a1,sp                   # delay slot
                
-skip_signal_return:
-               .set    noreorder
                .set    noat
-2:
-return:                RESTORE_ALL
+EXPORT(return) RESTORE_ALL
+               ERET
                .set    at
 
-#ifdef CONFIG_DESKSTATION_TYNE
 /*
- * Deskstation Tyne interrupt handler
- */
-               .text
-               .set    noreorder
-               .set    noat
-               .globl  _deskstation_tyne_handle_int
-               .align  5
-_deskstation_tyne_handle_int:
-               SAVE_ALL
-               .set    at
-               CLI
-               lui     s0,%hi(PORT_BASE)
-               li      t1,0x0f
-               sb      t1,%lo(PORT_BASE+0x20)(s0)      # poll command
-               lb      t1,%lo(PORT_BASE+0x20)(s0)      # read result
-               li      s1,1
-               bgtz    t1,Lpoll_second
-               andi    t1,t1,7
-               /*
-                * Acknowledge first pic
-                */
-               lb      t2,%lo(PORT_BASE+0x21)(s0)
-               lui     s4,%hi(_cache_21)
-               lb      t0,%lo(_cache_21)(s4)
-               sllv    s1,s1,t1
-               or      t0,t0,s1
-               sb      t0,%lo(_cache_21)(s4)
-               sb      t0,%lo(PORT_BASE+0x21)(s0)
-               lui     s3,%hi(_intr_count)
-               lw      t0,%lo(_intr_count)(s3)
-               li      t2,0x20
-               sb      t2,%lo(PORT_BASE+0x20)(s0)
-               /*
-                * Now call the real handler
-                */
-               la      t3,_IRQ_vectors
-               sll     t2,t1,2
-               addu    t3,t3,t2
-               lw      t3,(t3)
-               addiu   t0,t0,1
-               jalr    t3
-               sw      t0,%lo(_intr_count)(s3)         # delay slot
-               lw      t0,%lo(_intr_count)(s3)
-               /*
-                * Unblock first pic
-                */
-               lbu     t1,%lo(PORT_BASE+0x21)(s0)
-               lb      t1,%lo(_cache_21)(s4)
-               subu    t0,t0,1
-               sw      t0,%lo(_intr_count)(s3)
-               nor     s1,zero,s1
-               and     t1,t1,s1
-               sb      t1,%lo(_cache_21)(s4)
-               jr      v0
-               sb      t1,%lo(PORT_BASE+0x21)(s0)      # delay slot
-
-               .align  5
-Lpoll_second:  li      t1,0x0f
-               sb      t1,%lo(PORT_BASE+0xa0)(s0)      # poll command
-               lb      t1,%lo(PORT_BASE+0xa0)(s0)      # read result
-               lui     s4,%hi(_cache_A1)
-               bgtz    t1,Lspurious_interrupt
-               andi    t1,t1,7
-               /*
-                * Acknowledge second pic
-                */
-               lbu     t2,%lo(PORT_BASE+0xa1)(s0)
-               lb      t3,%lo(_cache_A1)(s4)
-               sllv    s1,s1,t1
-               or      t3,t3,s1
-               sb      t3,%lo(_cache_A1)(s4)
-               sb      t3,%lo(PORT_BASE+0xa1)(s0)
-               li      t3,0x20
-               sb      t3,%lo(PORT_BASE+0xa0)(s0)
-               lui     s3,%hi(_intr_count)
-               lw      t0,%lo(_intr_count)(s3)
-               sb      t3,%lo(PORT_BASE+0x20)(s0)
-               /*
-                * Now call the real handler
-                */
-               la      t0,_IRQ_vectors
-               sll     t2,t1,2
-               addu    t0,t0,t2
-               lw      t0,32(t0)
-               addiu   t0,t0,1
-               jalr    t0
-               sw      t0,%lo(_intr_count)(s3)         # delay slot
-               lw      t0,%lo(_intr_count)(s3)
-               /*
-                * Unblock second pic
-                */
-               lb      t1,%lo(PORT_BASE+0xa1)(s0)
-               lb      t1,%lo(_cache_A1)(s4)
-               subu    t0,t0,1
-               lw      t0,%lo(_intr_count)(s3)
-               nor     s1,zero,s1
-               and     t1,t1,s1
-               sb      t1,%lo(_cache_A1)(s4)
-               jr      v0
-               sb      t1,%lo(PORT_BASE+0xa1)(s0)      # delay slot
-
-               .align  5
-Lspurious_interrupt:
-               /*
-                * Nothing happened... (whistle)
-                */
-               lui     t1,%hi(_spurious_count)
-               lw      t0,%lo(_spurious_count)(t1)
-               la      v0,return
-               addiu   t0,t0,1
-               jr      ra
-               sw      t0,%lo(_spurious_count)(t1)
-#endif /* CONFIG_DESKSTATION_TYNE */
-               
-#ifdef CONFIG_ACER_PICA_61
-/*
- * Acer PICA interrupt handler dummy
+ * Beware: interrupt, fast_interrupt and bad_interrupt have unusal
+ * calling conventions to speedup the mess.
+ *
+ * t1 - interrupt number
+ * s2 - destroyed
+ * return values:
+ * v0 - return routine
  */
-               .set    noreorder
-               .set    noat
-               .globl  _acer_pica_61_handle_int
-               .align  5
-_acer_pica_61_handle_int:
-               la      a0,acer_text
-               jal     _panic
-               nop
-1:             b       1b
-               nop
-acer_text:     .asciz  "Interrupt handler for Acer PICA not written yet"
-               .align  2
-#endif /* CONFIG_ACER_PICA_61 */
-
                .text
-               .set    noreorder
                .set    at
-               .globl  _interrupt
                .align  5
-_interrupt:    move    s2,ra
-               mfc0    t0,CP0_STATUS
-               ori     t0,t0,0x1f
-               xori    t0,t0,0x1e
+NESTED(interrupt, FR_SIZE, sp)
+               move    s2,ra
+               mfc0    t0,CP0_STATUS                   # enable IRQs
+               ori     t0,0x1f
+               xori    t0,0x1e
                mtc0    t0,CP0_STATUS
                move    a0,t1
-               jal     _do_IRQ
+               jal     do_IRQ
                move    a1,sp                           # delay slot
-               mfc0    t0,CP0_STATUS
-               ori     t0,t0,1
-               xori    t0,t0,1
+               mfc0    t0,CP0_STATUS                   # disable IRQs
+               ori     t0,1
+               xori    t0,1
                la      v0,ret_from_sys_call
                jr      s2
                mtc0    t0,CP0_STATUS                   # delay slot
+               END(interrupt)
 
-               .globl  _fast_interrupt
                .align  5
-_fast_interrupt:
+NESTED(fast_interrupt, FR_SIZE, sp)
                move    s2,ra
                move    a0,t1
-               jal     _do_fast_IRQ
+               jal     do_fast_IRQ
                move    a1,sp                           # delay slot
-               la      v0,return
+               lui     v0,%hi(return)
                jr      s2
-               nop                                     # delay slot
+               addiu   v0,%lo(return)                  # delay slot
+               END(fast_interrupt)
 
-               .globl  _bad_interrupt
-_bad_interrupt:
+LEAF(bad_interrupt)
                /*
                 * Don't return & unblock the pic
                 */
                j       return
                nop
+               END(bad_interrupt)
 
-               .globl  _handle_tlbl
-               .align  5
-_handle_tlbl:
+/*
+ * do_syscall calls the function in a1 with upto 7 arguments.  If over
+ * four arguments are being requested, the additional arguments will
+ * be copied from the user stack pointed to by a0->reg29.
+ * Note that this routine relies on the GNU assemblers weak instruction
+ * scheduling abilities to generate the best possible code for all MIPS CPUs.
+ *
+ * a0 (struct pt_regs *)  pointer to user registers
+ * a1 (syscall_t)         pointer to syscall to do
+ * a2 (int)               number of arguments to syscall
+ */
                .set    noreorder
-               .set    noat
-               /*
-                * Check whether this is a refill or an invalid exception
-                *
-                * NOTE: Some MIPS manuals say that the R4x00 sets the
-                * BadVAddr only when EXL == 0. This is wrong - BadVaddr
-                * is being set for all Reload, Invalid and Modified
-                * exceptions.
-                */
-               mfc0    k0,CP0_BADVADDR
-               mfc0    k1,CP0_ENTRYHI
-               ori     k0,k0,0x1fff
-               xori    k0,k0,0x1fff
-               andi    k1,k1,0xff
-               or      k0,k0,k1
-               mfc0    k1,CP0_ENTRYHI
-               mtc0    k0,CP0_ENTRYHI
-               nop                                     # for R4[04]00 pipeline
-               nop
-               nop
-               tlbp
-               nop                                     # for R4[04]00 pipeline
-               nop
-               mfc0    k0,CP0_INDEX
-               srl     k0,k0,31
-               beqz    k0,invalid_tlbl
-               mtc0    k1,CP0_ENTRYHI                  # delay slot
-               /*
-                * Not in tlb -> nested refill exception
-                * Load the missing entry and return. This is the most
-                * efficient way to regain the faulting address.
-                */
-               dmfc0   k1,CP0_CONTEXT
-               dsra    k1,k1,1
-               lwu     k0,(k1)                 # Never causes another exception
-               lwu     k1,4(k1)
-               dsrl    k0,k0,6                 # Convert to EntryLo format
-               dsrl    k1,k1,6                 # Convert to EntryLo format
-               dmtc0   k0,CP0_ENTRYLO0
-               dmtc0   k1,CP0_ENTRYLO1
-               nop                             # for R4[04]00 pipeline
-               tlbwr
-               eret
-
-               /*
-                * Handle invalid exception
-                *
-                * There are two possible causes for an invalid (tlbl)
-                * exception:
-                * 1) pages that have the present bit set but the valid bit
-                *    unset.
-                * 2) pages that don't exist
-                * Case one needs fast handling, therefore don't save
-                * registers yet.
-                *
-                * k0 now contains the bad virtual address.
-                */
-invalid_tlbl:
-               /*
-                * Remove entry so we don't need to care later
-                */
-               mfc0    k0,CP0_INDEX
-               lui     k1,0x0008
-               or      k0,k0,k1
-               dsll    k0,k0,13
-               dmtc0   k0,CP0_ENTRYHI
-               dmtc0   zero,CP0_ENTRYLO0
-               dmtc0   zero,CP0_ENTRYLO1
-               /*
-                * Test whether present bit in entry is set
-                */
-               dmfc0   k0,CP0_BADVADDR
-               tlbwi                                           # delayed, for R4[04]00 pipeline
-               srl     k0,k0,10
-               lui     k1,%HI(TLBMAP)
-               addu    k0,k0,k1
-               ori     k0,k0,3
-               xori    k0,k0,3
-               lw      k1,(k0)
-               andi    k1,k1,_PAGE_PRESENT
-               beqz    k1,nopage_tlbl
-               /*
-                * Present bit is set -> set valid and accessed bits
-                */
-               lw      k1,(k0)                         # delay slot
-               ori     k1,k1,_PAGE_ACCESSED
-               sw      k1,(k0)
-               eret
-
-               /*
-                * Page doesn't exist. Lots of work which is less important
-                * for speed needs to be done, so hand it all over to the
-                * kernel memory management routines.
-                */
-nopage_tlbl:
-               SAVE_ALL
-               .set    at
-               STI
-               /*
-                * Create a Intel-style errorcode
-                * Bit 0: P Present
-                *        0 == Page not in memory
-                *        1 == privilege violation
-                * Bit 1: R/W Read/Write
-                *        0 == ReadAccess
-                *        1 == WriteAccess
-                * Bit 2: U/S User/Supervisor
-                *        0 == User mode
-                *        1 == Kernel mode
-                *
-                * a0 (struct pt_regs *) regs
-                * a1 (unsigned long)    error_code
-                */
-               lw      a1,FR_STATUS(sp)
-               move    a0,sp
-               srl     a1,a1,4
-               andi    a1,a1,1
-               jal     _do_page_fault
-               xori    a1,a1,1                         # delay slot
-               j       ret_from_sys_call
-               nop                                     # delay slot
-
                .text
-               .globl  _handle_tlbs
-               .align  5
-_handle_tlbs:
-               .set    noreorder
-               .set    noat
-               /*
-                * It is impossible that is a nested reload exception.
-                * Therefore this must be a invalid exception.
-                * Two possible cases:
-                * 1) Page not used yet
-                * 2) Page doesn't exist yet. Let the kernel handle the trouble.
-                *
-                * Test whether present bit in entry is set
-                */
-               dmfc0   k0,CP0_BADVADDR
-               srl     k0,k0,10
-               lui     k1,%HI(TLBMAP)
-               addu    k0,k0,k1
-               ori     k0,k0,3
-               xori    k0,k0,3
-               lw      k1,(k0)
-               andi    k1,k1,(_PAGE_PRESENT|_PAGE_RW)
-               beqz    k1,nopage_tlbs
-               /*
-                * Present and writable bits set -> set accessed and dirty bits.
-                */
-               lw      k1,(k0)                         # delay slot
-               ori     k1,k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-               sw      k1,(k0)
-               /*
-                * Now reload the entry into the tlb
-                */
-               ori     k0,k0,0x1000
-               xori    k0,k0,0x1000
-               lw      k1,4(k0)
-               lw      k0,(k0)
-               srl     k0,k0,6
-               srl     k1,k1,6
-               dmtc0   k0,CP0_ENTRYLO0
-               dmtc0   k1,CP0_ENTRYLO1
-               tlbwi
-               eret
-
-               /*
-                * Page doesn't exist. Lots of work which is less important
-                * for speed needs to be done, so hand it all over to the
-                * kernel memory management routines.
-                */
-nopage_tlbs:
-nowrite_mod:
-               /*
-                * Remove entry so we don't need to care later
-                */
-               mfc0    k0,CP0_INDEX
-               lui     k1,0x0008
-               or      k0,k0,k1
-               dsll    k0,k0,13
-               dmtc0   k0,CP0_ENTRYHI
-               dmtc0   zero,CP0_ENTRYLO0
-               dmtc0   zero,CP0_ENTRYLO1
-               tlbwi
-               SAVE_ALL
-               .set    at
-               STI
-               /*
-                * Create a Intel-style errorcode
-                * Bit 0: P Present
-                *        0 == Page not in memory
-                *        1 == privilege violation
-                * Bit 1: R/W Read/Write
-                *        0 == ReadAccess
-                *        1 == WriteAccess
-                * Bit 2: U/S User/Supervisor
-                *        0 == User mode
-                *        1 == Kernel mode
-                *
-                * a0 (struct pt_regs *) regs
-                * a1 (unsigned long)    error_code
-                */
-               lw      a1,FR_STATUS(sp)
-               move    a0,sp
-               srl     a1,a1,4
-               andi    a1,a1,1
-               jal     _do_page_fault
-               xori    a1,a1,3                         # branch delay slot
-               j       ret_from_sys_call
-               nop                                     # branch delay slot
-
-               .globl  _handle_mod
-               .align  5
-_handle_mod:
-               .set    noreorder
-               .set    noat
-               /*
-                * Two possible cases:
-                * 1) Page is rw but not dirty -> set dirty and return
-                * 2) Page is not rw -> call C handler
-                */
-               dmfc0   k0,CP0_BADVADDR
-               srl     k0,k0,10
-               lui     k1,%HI(TLBMAP)
-               addu    k0,k0,k1
-               ori     k0,k0,3
-               xori    k0,k0,3
-               lw      k1,(k0)
-               andi    k1,k1,_PAGE_RW
-               beqz    k1,nopage_tlbs
-               /*
-                * Present and writable bits set -> set accessed and dirty bits.
-                */
-               lw      k1,(k0)                         # delay slot
-               ori     k1,k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-               sw      k1,(k0)
-               /*
-                * Now reload the entry into the tlb
-                */
-               ori     k0,k0,0x1000
-               xori    k0,k0,0x1000
-               lw      k1,4(k0)
-               lw      k0,(k0)
-               srl     k0,k0,6
-               srl     k1,k1,6
-               dmtc0   k0,CP0_ENTRYLO0
-               dmtc0   k1,CP0_ENTRYLO1
-               tlbwi
-               eret
-
-               .globl  _handle_adel
-               .align  5
-_handle_adel:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_adel
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_ades
-               .align  5
-_handle_ades:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_ades
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_ibe
-               .align  5
-_handle_ibe:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_ibe
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_dbe
-               .align  5
-_handle_dbe:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_dbe
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_ov
-               .align  5
-_handle_ov:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_ov
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_fpe
-               .align  5
-_handle_fpe:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_fpe
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_bp
-               .align  5
-_handle_bp:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_bp
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_tr
-               .align  5
-_handle_tr:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_tr
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_ri
-               .align  5
-_handle_ri:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_ri
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_cpu
-               .align  5
-_handle_cpu:
+NESTED(do_syscalls, 32, sp)
+               subu    sp,32
+               sw      ra,28(sp)
+               sll     a2,a2,PTRLOG
+               lw      t0,dst(a2)
+               move    t2,a1
+               jalr    t0
+               lw      t0,FR_REG29(a0)         # get old user stack pointer
+
+               .set    reorder                 # for sake of R3000
+7:             lw      t1,24(t0)               # parameter #7 from usp
+               sw      t1,24(t0)
+6:             lw      t1,20(t0)               # parameter #6 from usp
+               sw      t1,20(t0)
+5:             lw      t1,16(t0)               # parameter #5 from usp
+               sw      t1,16(t0)
                .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_cpu
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_vcei
-               .align  5
-_handle_vcei:
+4:             lw      a3,FR_REG7(a0)          # 4 args
+3:             lw      a2,FR_REG6(a0)          # 3 args
+2:             lw      a1,FR_REG5(a0)          # 2 args
+1:             jalr    t2                      # 1 args
+               lw      a0,FR_REG4(a0)          # delay slot
+               .set    reorder
+               lw      ra,28(sp)
+               addiu   sp,32
+               jr      ra
+0:             jalr    t2                      # 0 args, just pass a0
+               lw      ra,28(sp)
+               addiu   sp,32
+               jr      ra
+               END(do_syscalls)
                .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_vcei
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
 
-               .globl  _handle_vced
-               .align  5
-_handle_vced:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_vced
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
+               .rdata
+               .align  PTRLOG
+dst:           PTR     0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
 
-               .globl  _handle_watch
-               .align  5
-_handle_watch:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_watch
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
-
-               .globl  _handle_reserved
-               .align  5
-_handle_reserved:
-               .set    noreorder
-               .set    noat
-               SAVE_ALL
-               STI
-               li      t0,-1
-               sw      t0,FR_ORIG_REG2(sp)
-               jal     _do_reserved
-               move    a0,sp                   # delay slot
-               j       ret_from_sys_call
-               nop                             # delay slot
+/*
+ * Build a default exception handler for the exceptions that don't need
+ * special handlers.  If you didn't know yet - I *like* playing games with
+ * the C preprocessor ...
+ */
+#define __BUILD_silent(exception)
+#define __BUILD_verbose(exception)                                      \
+               la      a1,8f;                                          \
+               TEXT    (#exception);                                   \
+               lw      a2,FR_EPC(sp);                                  \
+               PRINT("Got %s at %08x.\n")
+#define __BUILD_count(exception)                                        \
+               .set    reorder;                                        \
+               lw      t0,exception_count_##exception;                 \
+               addiu   t0,1;                                           \
+               sw      t0,exception_count_##exception;                 \
+               .set    noreorder;                                      \
+               .data;                                                  \
+EXPORT(exception_count_##exception);                                    \
+               .word   0;                                              \
+               .text;
+#define BUILD_HANDLER(exception,verbose)                                \
+               .text;                                                  \
+               .align  5;                                              \
+               NESTED(handle_##exception, FR_SIZE, sp);                \
+               .set    noat;                                           \
+               SAVE_ALL;                                               \
+               STI;                                                    \
+               .set    at;                                             \
+               __BUILD_##verbose(exception);                           \
+               li      t0,-1;                   /* not a sys call */   \
+               sw      t0,FR_ORIG_REG2(sp);                            \
+               jal     do_##exception;                                 \
+               move    a0,sp;                   /* delay slot */       \
+               j       ret_from_sys_call;                              \
+               nop;                             /* delay slot */       \
+               END(handle_##exception)
+
+               BUILD_HANDLER(adel,verbose)             /* #4  */
+               BUILD_HANDLER(ades,verbose)             /* #5  */
+               BUILD_HANDLER(ibe,verbose)              /* #6  */
+               BUILD_HANDLER(dbe,verbose)              /* #7  */
+               BUILD_HANDLER(sys,silent)               /* #8  */
+               BUILD_HANDLER(bp,verbose)               /* #9  */
+               BUILD_HANDLER(ri,verbose)               /* #10 */
+               BUILD_HANDLER(cpu,silent)               /* #11 */
+               BUILD_HANDLER(ov,verbose)               /* #12 */
+               BUILD_HANDLER(tr,verbose)               /* #13 */
+               BUILD_HANDLER(vcei,verbose)             /* #14 */
+               BUILD_HANDLER(fpe,verbose)              /* #15 */
+               BUILD_HANDLER(watch,verbose)            /* #23 */
+               BUILD_HANDLER(vced,verbose)             /* #31 */
+               BUILD_HANDLER(reserved,verbose)         /* others */
 
 /*
  * Exception handler table with 32 entries.
  * This might be extended to handle software exceptions
  */
                .bss
-               .globl  _exception_handlers
-               .align  2
-_exception_handlers:
-               .fill   32,4,0
+               .align  PTRLOG
+EXPORT(exception_handlers)
+               .fill   32,PTRSIZE,0
+
+/*
+ * Interrupt handler table with 16 entries.
+ */
+EXPORT(IRQ_vectors)
+               .fill   16,PTRSIZE,0
 
 /*
  * Table of syscalls
  */
                .data
-_sys_call_table:
-               .word   _sys_setup              /* 0 */
-               .word   _sys_exit
-               .word   _sys_fork
-               .word   _sys_read
-               .word   _sys_write
-               .word   _sys_open               /* 5 */
-               .word   _sys_close
-               .word   _sys_waitpid
-               .word   _sys_creat
-               .word   _sys_link
-               .word   _sys_unlink             /* 10 */
-               .word   _sys_execve
-               .word   _sys_chdir
-               .word   _sys_time
-               .word   _sys_mknod
-               .word   _sys_chmod              /* 15 */
-               .word   _sys_chown
-               .word   _sys_break
-               .word   _sys_stat
-               .word   _sys_lseek
-               .word   _sys_getpid             /* 20 */
-               .word   _sys_mount
-               .word   _sys_umount
-               .word   _sys_setuid
-               .word   _sys_getuid
-               .word   _sys_stime              /* 25 */
-               .word   _sys_ptrace
-               .word   _sys_alarm
-               .word   _sys_fstat
-               .word   _sys_pause
-               .word   _sys_utime              /* 30 */
-               .word   _sys_stty
-               .word   _sys_gtty
-               .word   _sys_access
-               .word   _sys_nice
-               .word   _sys_ftime              /* 35 */
-               .word   _sys_sync
-               .word   _sys_kill
-               .word   _sys_rename
-               .word   _sys_mkdir
-               .word   _sys_rmdir              /* 40 */
-               .word   _sys_dup
-               .word   _sys_pipe
-               .word   _sys_times
-               .word   _sys_prof
-               .word   _sys_brk                /* 45 */
-               .word   _sys_setgid
-               .word   _sys_getgid
-               .word   _sys_signal
-               .word   _sys_geteuid
-               .word   _sys_getegid            /* 50 */
-               .word   _sys_acct
-               .word   _sys_phys
-               .word   _sys_lock
-               .word   _sys_ioctl
-               .word   _sys_fcntl              /* 55 */
-               .word   _sys_mpx
-               .word   _sys_setpgid
-               .word   _sys_ulimit
-               .word   _sys_olduname
-               .word   _sys_umask              /* 60 */
-               .word   _sys_chroot
-               .word   _sys_ustat
-               .word   _sys_dup2
-               .word   _sys_getppid
-               .word   _sys_getpgrp            /* 65 */
-               .word   _sys_setsid
-               .word   _sys_sigaction
-               .word   _sys_sgetmask
-               .word   _sys_ssetmask
-               .word   _sys_setreuid           /* 70 */
-               .word   _sys_setregid
-               .word   _sys_sigsuspend
-               .word   _sys_sigpending
-               .word   _sys_sethostname
-               .word   _sys_setrlimit          /* 75 */
-               .word   _sys_getrlimit
-               .word   _sys_getrusage
-               .word   _sys_gettimeofday
-               .word   _sys_settimeofday
-               .word   _sys_getgroups          /* 80 */
-               .word   _sys_setgroups
-               .word   _sys_select
-               .word   _sys_symlink
-               .word   _sys_lstat
-               .word   _sys_readlink           /* 85 */
-               .word   _sys_uselib
-               .word   _sys_swapon
-               .word   _sys_reboot
-               .word   _sys_readdir
-               .word   _sys_mmap               /* 90 */
-               .word   _sys_munmap
-               .word   _sys_truncate
-               .word   _sys_ftruncate
-               .word   _sys_fchmod
-               .word   _sys_fchown             /* 95 */
-               .word   _sys_getpriority
-               .word   _sys_setpriority
-               .word   _sys_profil
-               .word   _sys_statfs
-               .word   _sys_fstatfs            /* 100 */
-               .word   _sys_ioperm
-               .word   _sys_socketcall
-               .word   _sys_syslog
-               .word   _sys_setitimer
-               .word   _sys_getitimer          /* 105 */
-               .word   _sys_newstat
-               .word   _sys_newlstat
-               .word   _sys_newfstat
-               .word   _sys_uname
-               .word   _sys_iopl               /* 110 */
-               .word   _sys_vhangup
-               .word   _sys_idle
-               .word   0 #_sys_vm86
-               .word   _sys_wait4
-               .word   _sys_swapoff            /* 115 */
-               .word   _sys_sysinfo
-               .word   _sys_ipc
-               .word   _sys_fsync
-               .word   _sys_sigreturn
-               .word   _sys_clone              /* 120 */
-               .word   _sys_setdomainname
-               .word   _sys_newuname
-               .word   0 #_sys_modify_ldt
-               .word   _sys_adjtimex
-               .word   _sys_mprotect           /* 125 */
-               .word   _sys_sigprocmask
-               .word   _sys_create_module
-               .word   _sys_init_module
-               .word   _sys_delete_module
-               .word   _sys_get_kernel_syms    /* 130 */
-               .word   _sys_quotactl
-               .word   _sys_getpgid
-               .word   _sys_fchdir
-               .word   _sys_bdflush
-               .word   _sys_sysfs              /* 135 */
-               .word   _sys_personality
-               .word   0                       /* for afs_syscall */
-               .word   _sys_setfsuid
-               .word   _sys_setfsgid
-               .word   _sys_llseek             /* 140 */
-               .space  (NR_syscalls-140)*4
+               .align  PTRLOG
+EXPORT(sys_call_table)
+               /*
+                * Reserved space for all the SVR4, SVR, BSD43 and POSIX
+                * flavoured syscalls.
+                */
+               .space  (__NR_Linux)*PTRSIZE
 
-               .bss
-               .globl  _IRQ_vectors
-_IRQ_vectors:  .fill   16,4,0
+               /*
+                * Linux flavoured syscalls.
+                */
+#define SYS(call, narg) PTR call
+#include "syscalls.h"
 
+/*
+ * Number of arguments of each syscall
+ */
+EXPORT(sys_narg_table)
+               /*
+                * Reserved space for all the SVR4, SVR, BSD43 and POSIX
+                * flavoured syscalls.
+                */
+               .space  (__NR_Linux)
+
+               /*
+                * Linux flavoured syscalls.
+                */
+#undef SYS
+#define SYS(call, narg) .byte narg
+#include "syscalls.h"
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
new file mode 100644 (file)
index 0000000..ea775e7
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * arch/mips/kernel/gdb-low.S
+ *
+ * gdb-low.S contains the low-level trap handler for the GDB stub.
+ *
+ * Copyright (C) 1995 Andreas Busse
+ */
+
+#include <linux/sys.h>
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/stackframe.h>
+#include <asm/gdb-stub.h>
+
+/*
+ * The low level trap handler
+ */
+               .align  5
+               NESTED(trap_low, GDB_FR_SIZE, sp)
+               .set    noat
+               .set    noreorder
+
+               mfc0    k0,CP0_STATUS
+               sll     k0,3                    /* extract cu0 bit */
+               bltz    k0,1f
+               move    k1,sp
+
+               /*
+                * Called from user mode, new stack
+                */
+               lui     k1,%hi(kernelsp)
+               lw      k1,%lo(kernelsp)(k1)
+1:             move    k0,sp
+               subu    sp,k1,GDB_FR_SIZE
+               sw      k0,GDB_FR_REG29(sp)
+               sw      v0,GDB_FR_REG2(sp)
+
+/*
+ * first save the CP0 and special registers
+ */
+
+               mfc0    v0,CP0_STATUS
+               sw      v0,GDB_FR_STATUS(sp)
+               mfc0    v0,CP0_CAUSE
+               sw      v0,GDB_FR_CAUSE(sp)
+               mfc0    v0,CP0_EPC
+               sw      v0,GDB_FR_EPC(sp)
+               mfc0    v0,CP0_BADVADDR
+               sw      v0,GDB_FR_BADVADDR(sp)
+               mfhi    v0
+               sw      v0,GDB_FR_HI(sp)
+               mflo    v0
+               sw      v0,GDB_FR_LO(sp)
+
+/*
+ * Now the integer registers
+ */
+
+               sw      zero,GDB_FR_REG0(sp)            /* I know... */
+               sw      $1,GDB_FR_REG1(sp)
+               /* v0 already saved */
+               sw      v1,GDB_FR_REG3(sp)
+               sw      a0,GDB_FR_REG4(sp)
+               sw      a1,GDB_FR_REG5(sp)
+               sw      a2,GDB_FR_REG6(sp)
+               sw      a3,GDB_FR_REG7(sp)
+               sw      t0,GDB_FR_REG8(sp)
+               sw      t1,GDB_FR_REG9(sp)
+               sw      t2,GDB_FR_REG10(sp)
+               sw      t3,GDB_FR_REG11(sp)
+               sw      t4,GDB_FR_REG12(sp)
+               sw      t5,GDB_FR_REG13(sp)
+               sw      t6,GDB_FR_REG14(sp)
+               sw      t7,GDB_FR_REG15(sp)
+               sw      s0,GDB_FR_REG16(sp)
+               sw      s1,GDB_FR_REG17(sp)
+               sw      s2,GDB_FR_REG18(sp)
+               sw      s3,GDB_FR_REG19(sp)
+               sw      s4,GDB_FR_REG20(sp)
+               sw      s5,GDB_FR_REG21(sp)
+               sw      s6,GDB_FR_REG22(sp)
+               sw      s7,GDB_FR_REG23(sp)
+               sw      t8,GDB_FR_REG24(sp)
+               sw      t9,GDB_FR_REG25(sp)
+               sw      k0,GDB_FR_REG26(sp)
+               sw      k1,GDB_FR_REG27(sp)
+               sw      gp,GDB_FR_REG28(sp)
+               /* sp already saved */
+               sw      fp,GDB_FR_REG30(sp)
+               sw      ra,GDB_FR_REG31(sp)
+
+               STI                             /* disable interrupts */
+               
+/*
+ * Followed by the floating point registers
+ */
+               mfc0    v0,CP0_STATUS           /* check if the FPU is enabled */
+               srl     v0,v0,16
+               andi    v0,v0,(ST0_CU1 >> 16)
+               beqz    v0,2f                   /* disabled, skip */
+               nop
+
+               swc1    $0,GDB_FR_FPR0(sp)
+               swc1    $1,GDB_FR_FPR1(sp)
+               swc1    $2,GDB_FR_FPR2(sp)
+               swc1    $3,GDB_FR_FPR3(sp)
+               swc1    $4,GDB_FR_FPR4(sp)
+               swc1    $5,GDB_FR_FPR5(sp)
+               swc1    $6,GDB_FR_FPR6(sp)
+               swc1    $7,GDB_FR_FPR7(sp)
+               swc1    $8,GDB_FR_FPR8(sp)
+               swc1    $9,GDB_FR_FPR9(sp)
+               swc1    $10,GDB_FR_FPR10(sp)
+               swc1    $11,GDB_FR_FPR11(sp)
+               swc1    $12,GDB_FR_FPR12(sp)
+               swc1    $13,GDB_FR_FPR13(sp)
+               swc1    $14,GDB_FR_FPR14(sp)
+               swc1    $15,GDB_FR_FPR15(sp)
+               swc1    $16,GDB_FR_FPR16(sp)
+               swc1    $17,GDB_FR_FPR17(sp)
+               swc1    $18,GDB_FR_FPR18(sp)
+               swc1    $19,GDB_FR_FPR19(sp)
+               swc1    $20,GDB_FR_FPR20(sp)
+               swc1    $21,GDB_FR_FPR21(sp)
+               swc1    $22,GDB_FR_FPR22(sp)
+               swc1    $23,GDB_FR_FPR23(sp)
+               swc1    $24,GDB_FR_FPR24(sp)
+               swc1    $25,GDB_FR_FPR25(sp)
+               swc1    $26,GDB_FR_FPR26(sp)
+               swc1    $27,GDB_FR_FPR27(sp)
+               swc1    $28,GDB_FR_FPR28(sp)
+               swc1    $29,GDB_FR_FPR29(sp)
+               swc1    $30,GDB_FR_FPR30(sp)
+               swc1    $31,GDB_FR_FPR31(sp)
+
+/*
+ * FPU control registers
+ */
+
+               mfc1    v0,CP1_STATUS
+               sw      v0,GDB_FR_FSR(sp)
+               mfc1    v0,CP1_REVISION
+               sw      v0,GDB_FR_FIR(sp)
+
+/*
+ * current stack frame ptr
+ */
+
+2:             sw      sp,GDB_FR_FRP(sp)
+
+/*
+ * CP0 registers (R4000/R4400 unused registers skipped)
+ */
+
+               mfc0    v0,CP0_INDEX
+               sw      v0,GDB_FR_CP0_INDEX(sp)
+               mfc0    v0,CP0_RANDOM
+               sw      v0,GDB_FR_CP0_RANDOM(sp)
+               mfc0    v0,CP0_ENTRYLO0
+               sw      v0,GDB_FR_CP0_ENTRYLO0(sp)
+               mfc0    v0,CP0_ENTRYLO1
+               sw      v0,GDB_FR_CP0_ENTRYLO1(sp)
+               mfc0    v0,CP0_PAGEMASK
+               sw      v0,GDB_FR_CP0_PAGEMASK(sp)
+               mfc0    v0,CP0_WIRED
+               sw      v0,GDB_FR_CP0_WIRED(sp)
+               mfc0    v0,CP0_ENTRYHI
+               sw      v0,GDB_FR_CP0_ENTRYHI(sp)
+               mfc0    v0,CP0_PRID
+               sw      v0,GDB_FR_CP0_PRID(sp)
+
+               .set    at
+
+/*
+ * continue with the higher level handler
+ */
+
+               move    a0,sp
+               jal     handle_exception
+               nop
+
+/*
+ * restore all writable registers, in reverse order
+ */
+
+               .set    noat
+
+               lw      v0,GDB_FR_CP0_ENTRYHI(sp)
+               lw      v1,GDB_FR_CP0_WIRED(sp)
+               mtc0    v0,CP0_ENTRYHI
+               mtc0    v1,CP0_WIRED
+               lw      v0,GDB_FR_CP0_PAGEMASK(sp)
+               lw      v1,GDB_FR_CP0_ENTRYLO1(sp)
+               mtc0    v0,CP0_PAGEMASK
+               mtc0    v1,CP0_ENTRYLO1
+               lw      v0,GDB_FR_CP0_ENTRYLO0(sp)
+               lw      v1,GDB_FR_CP0_INDEX(sp)
+               mtc0    v0,CP0_ENTRYLO0
+               mtc0    v1,CP0_INDEX
+
+/*
+ * Next, the floating point registers
+ */
+               mfc0    v0,CP0_STATUS           /* check if the FPU is enabled */
+               srl     v0,v0,16
+               andi    v0,v0,(ST0_CU1 >> 16)
+               beqz    v0,3f                   /* disabled, skip */
+               nop
+
+               lwc1    $31,GDB_FR_FPR31(sp)
+               lwc1    $30,GDB_FR_FPR30(sp)
+               lwc1    $29,GDB_FR_FPR29(sp)
+               lwc1    $28,GDB_FR_FPR28(sp)
+               lwc1    $27,GDB_FR_FPR27(sp)
+               lwc1    $26,GDB_FR_FPR26(sp)
+               lwc1    $25,GDB_FR_FPR25(sp)
+               lwc1    $24,GDB_FR_FPR24(sp)
+               lwc1    $23,GDB_FR_FPR23(sp)
+               lwc1    $22,GDB_FR_FPR22(sp)
+               lwc1    $21,GDB_FR_FPR21(sp)
+               lwc1    $20,GDB_FR_FPR20(sp)
+               lwc1    $19,GDB_FR_FPR19(sp)
+               lwc1    $18,GDB_FR_FPR18(sp)
+               lwc1    $17,GDB_FR_FPR17(sp)
+               lwc1    $16,GDB_FR_FPR16(sp)
+               lwc1    $15,GDB_FR_FPR15(sp)
+               lwc1    $14,GDB_FR_FPR14(sp)
+               lwc1    $13,GDB_FR_FPR13(sp)
+               lwc1    $12,GDB_FR_FPR12(sp)
+               lwc1    $11,GDB_FR_FPR11(sp)
+               lwc1    $10,GDB_FR_FPR10(sp)
+               lwc1    $9,GDB_FR_FPR9(sp)
+               lwc1    $8,GDB_FR_FPR8(sp)
+               lwc1    $7,GDB_FR_FPR7(sp)
+               lwc1    $6,GDB_FR_FPR6(sp)
+               lwc1    $5,GDB_FR_FPR5(sp)
+               lwc1    $4,GDB_FR_FPR4(sp)
+               lwc1    $3,GDB_FR_FPR3(sp)
+               lwc1    $2,GDB_FR_FPR2(sp)
+               lwc1    $1,GDB_FR_FPR1(sp)
+               lwc1    $0,GDB_FR_FPR0(sp)
+
+/*
+ * Now the CP0 and integer registers
+ */
+
+3:             mfc0    t0,CP0_STATUS
+               ori     t0,0x1f
+               xori    t0,0x1f
+               mtc0    t0,CP0_STATUS
+
+               lw      v0,GDB_FR_STATUS(sp)
+               lw      v1,GDB_FR_EPC(sp)
+               mtc0    v0,CP0_STATUS
+               mtc0    v1,CP0_EPC
+               lw      v0,GDB_FR_HI(sp)
+               lw      v1,GDB_FR_LO(sp)
+               mthi    v0
+               mtlo    v0
+               lw      ra,GDB_FR_REG31(sp)
+               lw      fp,GDB_FR_REG30(sp)
+               lw      gp,GDB_FR_REG28(sp)
+               lw      k1,GDB_FR_REG27(sp)
+               lw      k0,GDB_FR_REG26(sp)
+               lw      t9,GDB_FR_REG25(sp)
+               lw      t8,GDB_FR_REG24(sp)
+               lw      s7,GDB_FR_REG23(sp)
+               lw      s6,GDB_FR_REG22(sp)
+               lw      s5,GDB_FR_REG21(sp)
+               lw      s4,GDB_FR_REG20(sp)
+               lw      s3,GDB_FR_REG19(sp)
+               lw      s2,GDB_FR_REG18(sp)
+               lw      s1,GDB_FR_REG17(sp)
+               lw      s0,GDB_FR_REG16(sp)
+               lw      t7,GDB_FR_REG15(sp)
+               lw      t6,GDB_FR_REG14(sp)
+               lw      t5,GDB_FR_REG13(sp)
+               lw      t4,GDB_FR_REG12(sp)
+               lw      t3,GDB_FR_REG11(sp)
+               lw      t2,GDB_FR_REG10(sp)
+               lw      t1,GDB_FR_REG9(sp)
+               lw      t0,GDB_FR_REG8(sp)
+               lw      a3,GDB_FR_REG7(sp)
+               lw      a2,GDB_FR_REG6(sp)
+               lw      a1,GDB_FR_REG5(sp)
+               lw      a0,GDB_FR_REG4(sp)
+               lw      v1,GDB_FR_REG3(sp)
+               lw      v0,GDB_FR_REG2(sp)
+               lw      $1,GDB_FR_REG1(sp)
+               lw      sp,GDB_FR_REG29(sp)             /* Deallocate stack */
+
+               ERET
+               .set    at
+               .set    reorder
+               END(trap_low)
+
+/* end of file gdb-low.S */
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
new file mode 100644 (file)
index 0000000..7708fea
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ *  arch/mips/kernel/gdb-stub.c
+ *
+ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ *  Contributed by HP Systems
+ *
+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB      Set baud rate to BB..BB                OK or BNN, then sets
+ *                                                        baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/segment.h>
+#include <asm/cachectl.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+
+/*
+ * external low-level support routines
+ */
+
+extern int putDebugChar(char c);    /* write a single character      */
+extern char getDebugChar(void);     /* read and return a single char */
+extern void fltr_set_mem_err(void);
+extern void trap_low(void);
+
+/*
+ * breakpoint and test functions
+ */
+extern void breakpoint(void);
+extern void breakinst(void);
+extern void adel(void);
+
+/*
+ * local prototypes
+ */
+
+static void getpacket(char *buffer);
+static void putpacket(char *buffer);
+static void set_mem_fault_trap(int enable);
+static int computeSignal(int tt);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
+void handle_exception(struct gdb_regs *regs);
+static void show_gdbregs(struct gdb_regs *regs);
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+static int initialized = 0;    /* !0 means we've been initialized */
+static const char hexchars[]="0123456789abcdef";
+
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+       if (ch >= 'a' && ch <= 'f')
+               return ch-'a'+10;
+       if (ch >= '0' && ch <= '9')
+               return ch-'0';
+       if (ch >= 'A' && ch <= 'F')
+               return ch-'A'+10;
+       return -1;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+       unsigned char checksum;
+       unsigned char xmitcsum;
+       int i;
+       int count;
+       unsigned char ch;
+
+       do {
+               /*
+                * wait around for the start character,
+                * ignore all other characters
+                */
+               while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+               checksum = 0;
+               xmitcsum = -1;
+               count = 0;
+       
+               /*
+                * now, read until a # or end of buffer is found
+                */
+               while (count < BUFMAX) {
+                       ch = getDebugChar() & 0x7f;
+                       if (ch == '#')
+                               break;
+                       checksum = checksum + ch;
+                       buffer[count] = ch;
+                       count = count + 1;
+               }
+
+               if (count >= BUFMAX)
+                       continue;
+
+               buffer[count] = 0;
+
+               if (ch == '#') {
+                       xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+                       xmitcsum |= hex(getDebugChar() & 0x7f);
+
+                       if (checksum != xmitcsum)
+                               putDebugChar('-');      /* failed checksum */
+                       else {
+                               putDebugChar('+'); /* successful transfer */
+
+                               /*
+                                * if a sequence char is present,
+                                * reply the sequence ID
+                                */
+                               if (buffer[2] == ':') {
+                                       putDebugChar(buffer[0]);
+                                       putDebugChar(buffer[1]);
+
+                                       /*
+                                        * remove sequence chars from buffer
+                                        */
+                                       count = strlen(buffer);
+                                       for (i=3; i <= count; i++)
+                                               buffer[i-3] = buffer[i];
+                               }
+                       }
+               }
+       }
+       while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.
+ */
+static void putpacket(char *buffer)
+{
+       unsigned char checksum;
+       int count;
+       unsigned char ch;
+
+       /*
+        * $<packet info>#<checksum>.
+        */
+
+       do {
+               putDebugChar('$');
+               checksum = 0;
+               count = 0;
+
+               while ((ch = buffer[count]) != 0) {
+                       if (!(putDebugChar(ch)))
+                               return;
+                       checksum += ch;
+                       count += 1;
+               }
+
+               putDebugChar('#');
+               putDebugChar(hexchars[checksum >> 4]);
+               putDebugChar(hexchars[checksum & 0xf]);
+
+       }
+       while ((getDebugChar() & 0x7f) != '+');
+}
+
+
+/*
+ * Indicate to caller of mem2hex or hex2mem that there
+ * has been an error.
+ */
+static volatile int mem_err = 0;
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+       unsigned char ch;
+
+/*     set_mem_fault_trap(may_fault); */
+
+       while (count-- > 0) {
+               ch = *(mem++);
+               if (mem_err)
+                       return 0;
+               *buf++ = hexchars[ch >> 4];
+               *buf++ = hexchars[ch & 0xf];
+       }
+
+       *buf = 0;
+
+/*     set_mem_fault_trap(0); */
+
+       return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ */
+static char *hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+       int i;
+       unsigned char ch;
+
+/*     set_mem_fault_trap(may_fault); */
+
+       for (i=0; i<count; i++)
+       {
+               ch = hex(*buf++) << 4;
+               ch |= hex(*buf++);
+               *(mem++) = ch;
+               if (mem_err)
+                       return 0;
+       }
+
+/*     set_mem_fault_trap(0); */
+
+       return mem;
+}
+
+/*
+ * This table contains the mapping between SPARC hardware trap types, and
+ * signals, which are primarily what GDB understands.  It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static struct hard_trap_info
+{
+       unsigned char tt;               /* Trap type code for MIPS R3xxx and R4xxx */
+       unsigned char signo;            /* Signal that we map this trap into */
+} hard_trap_info[] = {
+       { 4, SIGBUS },                  /* address error (load) */
+       { 5, SIGBUS },                  /* address error (store) */
+       { 6, SIGBUS },                  /* instruction bus error */
+       { 7, SIGBUS },                  /* data bus error */
+       { 9, SIGTRAP },                 /* break */
+       { 10, SIGILL },                 /* reserved instruction */
+/*     { 11, SIGILL },         */      /* cpu unusable */
+       { 12, SIGFPE },                 /* overflow */
+       { 13, SIGTRAP },                /* trap */
+       { 14, SIGSEGV },                /* virtual instruction cache coherency */
+       { 15, SIGFPE },                 /* floating point exception */
+       { 23, SIGSEGV },                /* watch */
+       { 31, SIGSEGV },                /* virtual data cache coherency */
+       { 0, 0}                         /* Must be last */
+};
+
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void set_debug_traps(void)
+{
+       struct hard_trap_info *ht;
+
+       for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+               set_except_vector(ht->tt, trap_low);
+  
+       /*
+        * In case GDB is started before us, ack any packets
+        * (presumably "$?#xx") sitting there.
+        */
+
+       putDebugChar ('+');
+       initialized = 1;
+
+       breakpoint();
+}
+
+
+/*
+ * Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
+ * assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
+ * 0 would ever contain code that could mem fault.  This routine will skip
+ * past the faulting instruction after setting mem_err.
+ */
+extern void fltr_set_mem_err(void)
+{
+  /* FIXME: Needs to be written... */
+}
+
+
+static void set_mem_fault_trap(int enable)
+{
+  mem_err = 0;
+
+#if 0
+  if (enable)
+    exceptionHandler(9, fltr_set_mem_err);
+  else
+    exceptionHandler(9, trap_low);
+#endif  
+}
+
+/*
+ * Convert the MIPS hardware trap type code to a unix signal number.
+ */
+static int computeSignal(int tt)
+{
+       struct hard_trap_info *ht;
+
+       for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+               if (ht->tt == tt)
+                       return ht->signo;
+
+       return SIGHUP;          /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+       int numChars = 0;
+       int hexValue;
+
+       *intValue = 0;
+
+       while (**ptr)
+       {
+               hexValue = hex(**ptr);
+               if (hexValue < 0)
+                       break;
+
+               *intValue = (*intValue << 4) | hexValue;
+               numChars ++;
+
+               (*ptr)++;
+       }
+
+       return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.  It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+void handle_exception (struct gdb_regs *regs)
+{
+       int trap;                       /* Trap type */
+       int sigval;
+       int addr;
+       int length;
+       char *ptr;
+       unsigned long *stack;
+
+#if 0  
+       printk("in handle_exception()\n");
+       show_gdbregs(regs);
+#endif
+       
+       /*
+        * First check trap type. If this is CPU_UNUSABLE and CPU_ID is 1,
+        * the simply switch the FPU on and return since this is no error
+        * condition. kernel/traps.c does the same.
+        * FIXME: This doesn't work yet, so we don't catch CPU_UNUSABLE
+        * traps for now.
+        */
+       trap = (regs->cp0_cause & 0x7c) >> 2;
+/*     printk("trap=%d\n",trap); */
+       if (trap == 11) {
+               if (((regs->cp0_cause >> CAUSEB_CE) & 3) == 1) {
+                       regs->cp0_status |= ST0_CU1;
+                       return;
+               }
+       }
+
+       /*
+        * If we're in breakpoint() increment the PC
+        */
+       if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)             
+               regs->cp0_epc += 4;
+
+       stack = (long *)regs->reg29;                    /* stack ptr */
+       sigval = computeSignal(trap);
+
+       /*
+        * reply to host that an exception has occurred
+        */
+       ptr = output_buffer;
+
+       /*
+        * Send trap type (converted to signal)
+        */
+       *ptr++ = 'T';
+       *ptr++ = hexchars[sigval >> 4];
+       *ptr++ = hexchars[sigval & 0xf];
+
+       /*
+        * Send Error PC
+        */
+       *ptr++ = hexchars[REG_EPC >> 4];
+       *ptr++ = hexchars[REG_EPC & 0xf];
+       *ptr++ = ':';
+       ptr = mem2hex((char *)&regs->cp0_epc, ptr, 4, 0);
+       *ptr++ = ';';
+
+       /*
+        * Send frame pointer
+        */
+       *ptr++ = hexchars[REG_FP >> 4];
+       *ptr++ = hexchars[REG_FP & 0xf];
+       *ptr++ = ':';
+       ptr = mem2hex((char *)&regs->reg30, ptr, 4, 0);
+       *ptr++ = ';';
+
+       /*
+        * Send stack pointer
+        */
+       *ptr++ = hexchars[REG_SP >> 4];
+       *ptr++ = hexchars[REG_SP & 0xf];
+       *ptr++ = ':';
+       ptr = mem2hex((char *)&regs->reg29, ptr, 4, 0);
+       *ptr++ = ';';
+
+       *ptr++ = 0;
+       putpacket(output_buffer);       /* send it off... */
+
+       /*
+        * Wait for input from remote GDB
+        */
+       while (1) {
+               output_buffer[0] = 0;
+               getpacket(input_buffer);
+
+               switch (input_buffer[0])
+               {
+               case '?':
+                       output_buffer[0] = 'S';
+                       output_buffer[1] = hexchars[sigval >> 4];
+                       output_buffer[2] = hexchars[sigval & 0xf];
+                       output_buffer[3] = 0;
+                       break;
+
+               case 'd':
+                       /* toggle debug flag */
+                       break;
+
+               /*
+                * Return the value of the CPU registers
+                */
+               case 'g':
+                       ptr = output_buffer;
+                       ptr = mem2hex((char *)&regs->reg0, ptr, 32*4, 0); /* r0...r31 */
+                       ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*4, 0); /* cp0 */
+                       ptr = mem2hex((char *)&regs->fpr0, ptr, 32*4, 0); /* f0...31 */
+                       ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*4, 0); /* cp1 */
+                       ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*4, 0); /* frp */
+                       ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*4, 0); /* cp0 */
+                       break;
+         
+               /*
+                * set the value of the CPU registers - return OK
+                * FIXME: Needs to be written
+                */
+               case 'G':
+               {
+#if 0
+                       unsigned long *newsp, psr;
+
+                       ptr = &input_buffer[1];
+                       hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
+
+                       /*
+                        * See if the stack pointer has moved. If so, then copy the
+                        * saved locals and ins to the new location.
+                        */
+
+                       newsp = (unsigned long *)registers[SP];
+                       if (sp != newsp)
+                               sp = memcpy(newsp, sp, 16 * 4);
+
+#endif
+                       strcpy(output_buffer,"OK");
+                }
+               break;
+
+               /*
+                * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
+                */
+               case 'm':
+                       ptr = &input_buffer[1];
+
+                       if (hexToInt(&ptr, &addr)
+                               && *ptr++ == ','
+                               && hexToInt(&ptr, &length)) {
+                               if (mem2hex((char *)addr, output_buffer, length, 1))
+                                       break;
+                               strcpy (output_buffer, "E03");
+                       } else
+                               strcpy(output_buffer,"E01");
+                       break;
+
+               /*
+                * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
+                */
+               case 'M': 
+                       ptr = &input_buffer[1];
+
+                       if (hexToInt(&ptr, &addr)
+                               && *ptr++ == ','
+                               && hexToInt(&ptr, &length)
+                               && *ptr++ == ':') {
+                               if (hex2mem(ptr, (char *)addr, length, 1))
+                                       strcpy(output_buffer, "OK");
+                               else
+                                       strcpy(output_buffer, "E03");
+                       }
+                       else
+                               strcpy(output_buffer, "E02");
+                       break;
+
+               /*
+                * cAA..AA    Continue at address AA..AA(optional)
+                */
+               case 'c':    
+                       /* try to read optional parameter, pc unchanged if no parm */
+
+                       ptr = &input_buffer[1];
+                       if (hexToInt(&ptr, &addr))
+                               regs->cp0_epc = addr;
+         
+                       /*
+                        * Need to flush the instruction cache here, as we may
+                        * have deposited a breakpoint, and the icache probably
+                        * has no way of knowing that a data ref to some location
+                        * may have changed something that is in the instruction
+                        * cache.
+                        * NB: We flush both caches, just to be sure...
+                        */
+
+                       sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE);
+                       return;
+                       /* NOTREACHED */
+                       break;
+
+
+               /*
+                * kill the program
+                */
+               case 'k' :
+                       break;          /* do nothing */
+
+
+               /*
+                * Reset the whole machine (FIXME: system dependent)
+                */
+               case 'r':
+                       break;
+
+
+               /*
+                * Step to next instruction
+                * FIXME: Needs to be written
+                */
+               case 's':
+                       strcpy (output_buffer, "S01");
+                       break;
+
+               /*
+                * Set baud rate (bBB)
+                * FIXME: Needs to be written
+                */
+               case 'b':
+               {
+#if 0                          
+                       int baudrate;
+                       extern void set_timer_3();
+
+                       ptr = &input_buffer[1];
+                       if (!hexToInt(&ptr, &baudrate))
+                       {
+                               strcpy(output_buffer,"B01");
+                               break;
+                       }
+
+                       /* Convert baud rate to uart clock divider */
+
+                       switch (baudrate)
+                       {
+                               case 38400:
+                                       baudrate = 16;
+                                       break;
+                               case 19200:
+                                       baudrate = 33;
+                                       break;
+                               case 9600:
+                                       baudrate = 65;
+                                       break;
+                               default:
+                                       baudrate = 0;
+                                       strcpy(output_buffer,"B02");
+                                       goto x1;
+                       }
+
+                       if (baudrate) {
+                               putpacket("OK");        /* Ack before changing speed */
+                               set_timer_3(baudrate); /* Set it */
+                       }
+#endif
+               }
+               break;
+
+               }                       /* switch */
+
+               /*
+                * reply to the request
+                */
+
+               putpacket(output_buffer);
+
+       } /* while */
+}
+
+/*
+ * This function will generate a breakpoint exception.  It is used at the
+ * beginning of a program to sync up with a debugger and can be used
+ * otherwise as a quick means to stop program execution and "break" into
+ * the debugger.
+ */
+void breakpoint(void)
+{
+       if (!initialized)
+               return;
+
+       __asm__ __volatile__("
+                       .globl  breakinst
+                       .set    noreorder
+                       nop
+breakinst:             break
+                       nop
+                       .set    reorder
+       ");
+}
+
+void adel(void)
+{
+       __asm__ __volatile__("
+                       .globl  adel
+                       la      $8,0x80000001
+                       lw      $9,0($8)
+       ");
+}
+
+/*
+ * Print registers (on target console)
+ * Used only to debug the stub...
+ */
+void show_gdbregs(struct gdb_regs * regs)
+{
+       /*
+        * Saved main processor registers
+        */
+       printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg0, regs->reg1, regs->reg2, regs->reg3,
+               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+       printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg8, regs->reg9, regs->reg10, regs->reg11,
+               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+       printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg16, regs->reg17, regs->reg18, regs->reg19,
+               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+       printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg24, regs->reg25, regs->reg26, regs->reg27,
+              regs->reg28, regs->reg29, regs->reg30, regs->reg31);
+
+       /*
+        * Saved cp0 registers
+        */
+       printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
+              regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+}
index d204955313f922ee83ac03d56ad39bd9ecd6b4a6..d26a41d16027a29c72d2676042492ce5f5c4c4f7 100644 (file)
@@ -1,47 +1,28 @@
 /*
- *  mips/head.S
+ *  arch/mips/kernel/head.S
  *
- *  Copyright (C) 1994 Waldorf Electronics
+ *  Copyright (C) 1994, 1995 Waldorf Electronics
  *  Written by Ralf Baechle and Andreas Busse
  *
  *  Head.S contains the MIPS exception handler and startup code.
  */
-
-#undef DEBUGPICA /* undef this if you have a different system */
-
 #include <linux/tasks.h>
 
+#include <asm/asm.h>
 #include <asm/segment.h>
 #include <asm/cachectl.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/stackframe.h>
-#include <asm/regdef.h>
 #include <asm/bootinfo.h>
-#include <asm/segment.h>
 
 #define PAGE_SIZE      0x1000
 
-/*
- * For now we can't enable write caching. This would cause trouble
- * with the page aliases used by the memory management.
- * The page table's aliases even have to be uncachable, but that
- * doesn't hurt much anyway.
- */
-#define PAGE_TABLE     0x0580  /* uncachable */
-#define PAGE_SHARED    0x0580  /* cachable, writethrough, no write allocate */
+#define MODE_GLOBAL    0x0001  /* shared for all processes */
 #define MODE_ALIAS     0x0016  /* uncachable */
 
-               .globl  _empty_bad_page
-               .globl  _empty_bad_page_table
-               .globl  _pg0
-               .globl  _empty_zero_page
-               .globl  _swapper_pg_dir
-
                .text
-               .globl  _kernelbase
-_kernelbase:
-
+               .set    mips3
 /*
  * This is space for the interrupt handlers.
  * They are located at virtual address KSEG[01] (physical 0x0)
@@ -51,92 +32,80 @@ _kernelbase:
                 */
                .set    noreorder
                .set    noat
-except_vec0:
-#if KERNELBASE == KSEG1
-               la      k0,1f
-               jr      k0
-               nop
-1:
-#endif
+               LEAF(except_vec0)
                dmfc0   k1,CP0_CONTEXT
-               dsra    k1,k1,1
+               dsra    k1,1
                lwu     k0,(k1)                 # May cause another exception
                lwu     k1,4(k1)
-               dsrl    k0,k0,6                 # Convert to EntryLo format
-               dsrl    k1,k1,6                 # Convert to EntryLo format
+               dsrl    k0,6                    # Convert to EntryLo format
+               dsrl    k1,6                    # Convert to EntryLo format
                dmtc0   k0,CP0_ENTRYLO0
                dmtc0   k1,CP0_ENTRYLO1
+               nop                             # Needed for R4[04]00 pipeline
                tlbwr
+               nop                             # Needed for R4[04]00 pipeline
+               nop
+               nop
+               eret
+               /*
+                * Workaround for R4000 bug.  For explanation see MIPS
+                * docs.  Note that this that obscure that it wont almost
+                * never happen.  Well, but Mips writes about it's bugs.
+                */
+               nop
                eret
+               END(except_vec0)
 
                /*
                 * XTLB refill, EXL == 0
                 * Should never be reached
                 */
                .org    except_vec0+0x80
-except_vec1:   
-#if KERNELBASE == KSEG1
-               la      k0,1f
-               jr      k0
-               nop
-1:
-#endif
-               la      a0,xtlb_text
-               jal     _panic
-               nop
+               LEAF(except_vec1)
+               PANIC("XTLB Refill exception.\n")
 1:             j       1b
                nop
-xtlb_text:     .asciz  "XTLB Refill exception.\n"
+               END(except_vec1)
 
                /*
                 * Cache Error
                 */
                .org    except_vec1+0x80
-except_vec2:
-#if KERNELBASE == KSEG1
-               la      k0,1f
-               jr      k0
-               nop
-1:
-#endif
+               LEAF(except_vec2)
                /*
-                * Should never be reached
+                * Famous last words: unreached
                 */
-               la      a0,xtlb_text
-               jal     _panic
-               nop
+               mfc0    a1,CP0_ERROREPC
+               PRINT("Cache error exception: c0_errorepc == %08x\n")
 1:             j       1b
                nop
-cache_text:    .asciz  "Cache error exception\n"
+               END(except_vec2)
 
                /*
                 * General exception vector.
                 */
                .org    except_vec2+0x80
-except_vec3:   /*
+               NESTED(except_vec3, 0, sp)
+               .set    noat
+               /*
                 * Register saving is delayed as long as we don't know
                 * which registers really need to be saved.
                 */
-#if KERNELBASE == KSEG1
-               la      k0,1f
-               jr      k0
-               nop
-1:
-#endif
-               .set    noat
                mfc0    k1,CP0_CAUSE
-               la      k0,_exception_handlers
+               la      k0,exception_handlers
                /*
                 * Next lines assumes that the used CPU type has max.
                 * 32 different types of exceptions. We might use this
                 * to implement software exceptions in the future.
                 */
-               andi    k1,k1,0x7c
-               addu    k0,k0,k1
+               andi    k1,0x7c
+               addu    k0,k1
                lw      k0,(k0)
-               FILL_LDS
+               NOP
                jr      k0
                nop
+               END(except_vec3)
+               .set    at
 
 /******************************************************************************/
 
@@ -144,88 +113,84 @@ except_vec3:      /*
  * Kernel entry
  */
                .set    noreorder
-               .set    at
-kernel_entry:
-               jal     refill
-               nop
+               NESTED(kernel_entry, 16, sp)
+               /*
+                * The followin two symbols are used for kernel profiling.
+                */
+               EXPORT(stext)
+               EXPORT(_stext)
 
+#ifdef CONF_DISABLE_KSEG0_CACHING
+               /*
+                * Disable all caching for KSEG0.  This option is usefull
+                * when cache trouble with drivers is suspected
+                */
+               mfc0    t0,CP0_CONFIG
+               ori     t0,7
+               xori    t0,5
+               mtc0    t0,CP0_CONFIG
+#endif
                /*
                 * Clear BSS first so that there are no surprises...
                 */
-               la      t0,__edata
-               la      t1,__end
+               la      t0,_edata
+               la      t1,_end
                sw      zero,(t0)
-1:             addiu   t0,t0,4
+1:             addiu   t0,4
                bnel    t0,t1,1b
                sw      zero,(t0)
 
-#ifdef DEBUGPICA
-               la      t0,_boot_info
-               lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
-               li      t1,0x0f00 + '3'
-               sh      t1,4(t0)
-#endif
-
-               .set    noreorder
-               jal     _tlbflush
-               mtc0    zero,CP0_WIRED
-               /*
-                * Spread some mines...
-                */
-               la      t0,_end
-               la      t1,0x003ffffc
-               la      t2,KERNELBASE
-               or      t1,t2
-               li      t2,0xdeadbeef
-1:             sw      t2,(t0)
-               bne     t0,t1,1b
-               addiu   t0,t0,4
                /*
-                * Initialize memory management, map lowest 4MB
+                * Initialize low level part of memory management
+                * First flush the TLB to make shure that we don't get a
+                * TLB shutdown during wire_mappings.
                 */
-               .set    reorder
-               jal     setup_paging
-#if KERNELBASE == KSEG0
-               jal     _sys_cacheflush
-#endif
+               jal     tlbflush
+               mtc0    zero,CP0_WIRED                  # delay slot
+               jal     wire_mappings
+               nop
 
-#ifdef DEBUGPICA
-               la      t0,_boot_info
-               lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
-               li      t1,0x0f00 + '4'
-               sh      t1,6(t0)
-#endif
                /*
                 * Stack for kernel and init
                 */
-               la      sp,_init_user_stack+PAGE_SIZE-24
-               sw      sp,_kernelsp
+               la      sp,init_user_stack+PAGE_SIZE-24
+               la      t0,init_kernel_stack+PAGE_SIZE
+               sw      t0,kernelsp
 
-1:             jal     _start_kernel
+               /*
+                * Disable coprocessors; set ST0_CU0 to indicate that
+                * we're running on the kernel stack
+                */
+               mfc0    t0,CP0_STATUS
+               li      t1,~(ST0_CU1|ST0_CU2|ST0_CU3)
+               and     t0,t1
+               li      t1,ST0_CU0
+               or      t0,ST0_CU0
+               mtc0    t0,CP0_STATUS
+
+1:             jal     start_kernel
+               nop                                     # delay slot
                /*
                 * Main should never return here, but
                 * just in case, we know what happens.
                 */
-               j       1b
+               b       1b
+               nop                                     # delay slot
+               END(kernel_entry)
 
 /*
- * Setup_paging
- *
- * Wire mappings for page_tables.
- * The page tables are set up, identity-mapping
- * the first 4MB.  The rest are initialized later.
+ * wire_mappings - used to map hardware registers
  */
-               .set    noreorder
-setup_paging:
+               LEAF(wire_mappings)
                /*
-                * get base address of map0 table for the
+                * Get base address of map0 table for the
                 * the board we're running on
                 */
-               la      t0,_boot_info
+               la      t0,boot_info
                lw      t1,OFFSET_BOOTINFO_MACHTYPE(t0)
-               sll     t1,t1,2                 # machtype used as index
                la      t0,map0table
-               addu    t0,t0,t1
+               sll     t1,PTRLOG               # machtype used as index
+               addu    t0,t1
                lw      t0,(t0)                 # get base address
 
                /*
@@ -237,20 +202,20 @@ setup_paging:
                addiu   t3,t1,1                 # wire one additional entry
                beqz    t1,2f                   # null, exit
                mtc0    t3,CP0_WIRED            # delay slot
-               addiu   t0,t0,8
+               addiu   t0,8
 1:             lw      t4,24(t0)               # PageMask
                ld      t5,0(t0)                # entryHi
                ld      t6,8(t0)                # entryLo0
                ld      t7,16(t0)               # entryLo1
-               addiu   t2,t2,1                 # increment ctr
+               addiu   t2,1                    # increment ctr
                mtc0    t2,CP0_INDEX            # set TLB entry
                mtc0    t4,CP0_PAGEMASK
                dmtc0   t5,CP0_ENTRYHI
                dmtc0   t6,CP0_ENTRYLO0
                dmtc0   t7,CP0_ENTRYLO1
-               tlbwi 
+               addiu   t0,32
                bne     t1,t2,1b                # next TLB entry
-               addiu   t0,t0,32                # delay slot
+               tlbwi                           # delay slot
 
                /*
                 * We use only 4k pages. Therefore the PageMask register
@@ -259,182 +224,45 @@ setup_paging:
 2:             li      t0,PM_4K
                mtc0    t0,CP0_PAGEMASK
 
-               la      t1,_swapper_pg_dir      # swapper_pg_dir is at 0x1000
-               la      t2,_swapper_pg_dir+(PAGE_SIZE-4)
-1:             sw      zero,(t1)
-               bne     t1,t2,1b
-               addiu   t1,t1,4                 # delay slot
-
-               /*
-                * Setup invalid_pg_table and
-                * clear page table for the first 4MB
-                */
-               la      t0,_pg0                 # swapper_pg_dir is at 0x1000
-               la      t1,_pg0+PAGE_SIZE
-               li      t2,KERNELBASE
-               addu    t0,t2
-               addu    t1,t2
-1:             sw      zero,(t0)
-               addiu   t0,t0,4
-               bne     t0,t1,1b
-               addiu   t2,t2,4                 # delay slot
-
-               /*
-                * Identity-map the kernel in low 4MB memory for ease
-                * of transition. Unlike the Intel version the kernel
-                * code/data is automagically being mapped by kseg0.
-                */
-               la      t0,_pg0+PAGE_TABLE      # set valid bit/user r/w
-               sw      t0,_swapper_pg_dir
-
-               li      t0,PAGE_SHARED          # set valid bit/user r/w
-               la      t1,_pg0
-               la      t2,_pg0+PAGE_SIZE
-               li      t3,KERNELBASE
-               addu    t1,t3
-               addu    t2,t3
-1:             sw      t0,(t1)
-               addiu   t1,t1,4
-               bne     t1,t2,1b
-               addiu   t0,t0,PAGE_SIZE         # delay slot
-
                /*
                 * Now map the pagetables
                 */
                mtc0    zero,CP0_INDEX
                la      t0,TLB_ROOT
                dmtc0   t0,CP0_ENTRYHI
-               la      t0,_swapper_pg_dir
-               srl     t0,t0,6
-               ori     t0,t0,MODE_ALIAS        # uncachable, dirty, valid
+               la      t0,swapper_pg_dir-KSEG1
+               srl     t0,6
+               ori     t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid
                dmtc0   t0,CP0_ENTRYLO0
-               dmtc0   zero,CP0_ENTRYLO1
-               tlbwi
-               /*
-                * Make page zero unaccessible to catch zero references
-                */
-               la      t0,_pg0
-               li      t0,KERNELBASE
-               addu    t0,t1
-               sw      zero,(t0)
+               li      t0,MODE_GLOBAL
+               dmtc0   t0,CP0_ENTRYLO1
+               nop
+               tlbwi                           # delayed
+
                /*
                 * Load the context register with a value that allows
                 * it to be used as fast as possible in tlb exceptions.
-                * It is expected that this register's content never
-                * will be changed.
+                * It is expected that this register's content will
+                * NEVER be changed.
                 */
                li      t0,TLBMAP
-               dsll    t0,t0,1
-               jr      ra
-               dmtc0   t0,CP0_CONTEXT          # delay slot
-
-               /*
-                * Flush the TLB
-                *
-                * FIXME: knows only how to handle R4x00
-                * Read appendix f of the R4000 manual before you change
-                * something!
-                */
-               .globl  _tlbflush
-_tlbflush:     li      t0,PM_4K
-               mtc0    t0,CP0_PAGEMASK
-               lw      t0,_boot_info+OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-               dmtc0   zero,CP0_ENTRYLO0
-               dmtc0   zero,CP0_ENTRYLO1
-               mfc0    t2,CP0_WIRED
-1:             subu    t0,t0,1
-               mtc0    t0,CP0_INDEX
-               lui     t1,0x0008
-               or      t1,t0,t1
-               dsll    t1,t1,13
-               dmtc0   t1,CP0_ENTRYHI
-               bne     t2,t0,1b
-               tlbwi                                   # delay slot
-               jr      ra
-               nop
-
-/*
- * Refill icache
- */
-#include <asm/mipsconfig.h>
-#include <asm/regdef.h>
-#include <asm/segment.h>
-
-#define PAGE_SIZE      0x1000
-
-#define CACHELINES     512             /* number of cachelines    */
-
-               .set    noreorder
-               .text
-refill:
-               /*
-                * Refill icache with cache fill command
-                */
-               li      t0,KSEG0
-               li      t1,CACHELINES
-1:             cache   21,0(t0)
-               cache   21,32(t0)
-               cache   21,64(t0)
-               cache   21,96(t0)
-               cache   21,128(t0)
-               cache   21,160(t0)
-               cache   21,192(t0)
-               cache   21,224(t0)
-               cache   21,256(t0)
-               cache   21,288(t0)
-               cache   21,320(t0)
-               cache   21,352(t0)
-               cache   21,384(t0)
-               cache   21,416(t0)
-               cache   21,448(t0)
-               cache   21,480(t0)
-               subu    t1,t1,1
-               bnez    t1,1b
-               addiu   t0,t0,512                       # delay slot
-
-               jr      ra
-               nop
-
-/*
- * Just for debugging...
- */
-               .globl  _beep
-_beep:         lw      t0,beepflag
-               nop
-               bnez    t0,1f
-               lbu     t0,0xe0000061
-               xori    t0,t0,3
-               sb      t0,0xe0000061
-               li      t0,1
-               sw      t0,beepflag
-1:             jr      ra
+               dsll    t0,1
+               dmtc0   t0,CP0_CONTEXT
+               jr      ra                      # delay slot
                nop
+               END(wire_mappings)
 
+               .data
 /*
- * Compute kernel code checksum to check kernel code against corruption
+ * Build an entry for table of wired entries
  */
-               .globl  _csum
-#if 0
-_csum:         jal     _sys_cacheflush
-               move    t8,ra                   # delay slot
-#else
-_csum:         move    t8,ra
-#endif
-               li      t0,KSEG1
-               la      t1,final
-               li      t2,KSEG1
-               or      t0,t2
-               or      t1,t2
-               move    v0,zero
-1:             lw      t2,(t0)
-               addiu   t0,t0,4
-               bne     t0,t1,1b
-               xor     v0,v0,t2
-               jr      t8
-               nop
-final:
+#define MAPDATA(q1,q2,q3,w1)                                    \
+               .quad   q1;                                     \
+               .quad   q2;                                     \
+               .quad   q3;                                     \
+               .word   w1;                                     \
+               .word   0
 
-               .data
 /*
  * Initial mapping tables for supported Mips boards.
  * First item is always the number of wired TLB entries,
@@ -449,288 +277,104 @@ final:
  * target system in bootinfo.h
  */
 
-map0table:     .word   map0_dummy              # machtype = unknown
-               .word   map0_tyne               # Deskstation Tyne
-               .word   map0_pica61             # Acer Pica-61
+map0table:     PTR     map0_dummy              # machtype = unknown
+               PTR     map0_rpc                # Deskstation rPC44
+               PTR     map0_tyne               # Deskstation Tyne
+               PTR     map0_pica61             # Acer Pica-61
+               PTR     map0_magnum4000         # MIPS Magnum 4000PC (RC4030)
 
 map0_dummy:    .word   0                       # 0 entries
 
+               .align  3
 /*
- * Initial mappings for Deskstation Tyne boards.
+ * Initial mappings for Deskstation rPC boards.
+ * RB: Untested goodie - I don't have such a board.
  */
-               .align  8
-
-map0_tyne:     .word   3                       # no. of wired TLB entries
+map0_rpc:      .word   2                       # no. of wired TLB entries
                .word   0                       # pad for alignment
 
-# TLB entry 1: ISA I/O
-
-               .quad   0xffffffffe0000000      # TLB #0 EntryHi
-               .quad   0x24000017              # TLB #0 EntryLo0
-               .quad   0                       # TLB #0 EntryLo1
-               .word   PM_64K                  # page mask
-               .word   0                       # pad for alignment
+MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)     # VESA DMA cache
+MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)    # VESA I/O and memory space
 
-# TLB entry 2: ISA memory space
-
-               .quad   0xffffffffe1000000      # TLB #1 EntryHi
-               .quad   0x04000017              # TLB #1 EntryLo0
-               .quad   0                       # TLB #1 EntryLo1
-               .word   PM_1M
+/*
+ * Initial mappings for Deskstation Tyne boards.
+ */
+map0_tyne:     .word   2                       # no. of wired TLB entries
                .word   0                       # pad for alignment
 
-# TLB entry 3: ISA DMA cache
-
-               .quad   0xffffffffe2000000      # TLB #2 EntryHi
-               .quad   0x04020017              # TLB #2 EntryLo0
-               .quad   0                       # TLB #2 EntryLo1
-               .word   PM_1M
-               .word   0                       # pad for alignment
+MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)     # VESA DMA cache
+MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)    # VESA I/O and memory space
 
 /*
  * Initial mapping for ACER PICA-61 boards.
- * FIXME: These are rather preliminary since many drivers,
- * such as serial, parallel, scsi and ethernet need some
- * changes to distinguish between "local" (built-in) and
- * "optional" (ISA/PCI) I/O hardware.
- * Local video ram is mapped to the same location as the
- * bios maps it to. Console driver has been changed
+ * FIXME: These are rather preliminary since many drivers, such as serial,
+ * parallel, scsi and ethernet need some changes to distinguish between "local"
+ * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped
+ * to the same location as the bios maps it to. Console driver has been changed
  * accordingly (new video type: VIDEO_TYPE_PICA_S3).
+ * FIXME: Remove or merge some of the mappings.
  */
-
-map0_pica61:   .word   9                       # no. wired TLB entries
+map0_pica61:   .word   7                       # no. wired TLB entries
                .word   0                       # dummy
 
-# TLB entry 1: PROM
-
-#              .quad   0xffffffffe1000000      # BIOS mapping
-               .quad   0xffffffffe4000000      # new mapping
-               .quad   0x03ffc013
-               .quad   0x00000001              # global, not valid
-               .word   PM_256K
-               .word   0
-
-# TLB entry 2: local I/O space
-
-               .quad   0xffffffffe0000000
-               .quad   0x02000017
-               .quad   0x00000001              # global, not valid
-               .word   PM_64K
-               .word   0
-
-# TLB entry 3: DRAM config register
-
-               .quad   0xffffffffe00e0000
-               .quad   0x02003817
-               .quad   0x02003c17
-               .word   PM_64K
-               .word   0
-
-# TLB entry 4: Interrupt source register
-
-               .quad   0xffffffffe0100000
-               .quad   0x03c00017
-               .quad   0x00000001              # global, not valid
-               .word   PM_4K
-               .word   0
-
-# TLB entry 5: Local video control
-
-               .quad   0xffffffffe0200000
-               .quad   0x01800017
-               .quad   0x01804017
-               .word   PM_1M
-               .word   0
-
-# TLB entry 6: Extended video control
-
-               .quad   0xffffffffe0400000
-               .quad   0x01808017
-               .quad   0x0180c017
-               .word   PM_1M
-               .word   0
-
-# TLB entry 7: Local video memory (BIOS mapping)
-
-               .quad   0xffffffffe0800000
-               .quad   0x01000017
-               .quad   0x01010017
-               .word   PM_4M
-               .word   0
-
-# TLB entry 8: Local video memory (mapped to where Linux expects it)
-# not needed anymore
-#              .quad   0xffffffffe1000000
-#              .quad   0x01000017
-#              .quad   0x01010017
-#              .word   PM_4M
-#              .word   0
-
-# TLB entry 9: ISA I/O and ISA memory space (both 16M)
-
-               .quad   0xffffffffe2000000
-               .quad   0x02400017
-               .quad   0x02440017
-               .word   PM_16M
-               .word   0
-
-# TLB entry 10: PCR (???)
-
-               .quad   0xffffffffffffe000
-               .quad   0x00000001              # nonsense...
-               .quad   0x0001ffd7
-               .word   PM_4K
-               .word   0
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)    # Local I/O space
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)     # Interrupt source register
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)     # Local video control
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)     # Extended video control
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)     # Local video memory (BIOS mapping)
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)    # ISA I/O and ISA memory space (both 16M)
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)     # PCR (???)
 
+/*
+ * Initial mapping for Mips Magnum 4000PC systems.
+ * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
+ * FIXME: Remove or merge some of the mappings.
+ */
 
-/* ------------------------------------------------
- * Mapping as presented by the PICA BIOS.
- * This table works. Please leave unmodified!
- * ------------------------------------------------ */
-#if 0
-map0_pica61:   .word   11                      # no. wired TLB entries
+map0_magnum4000:
+               .word   8                       # no. wired TLB entries
                .word   0                       # dummy
 
-# TLB entry 0: Don't know what this is good for...
+MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, 0x7e000)   # 0
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, 0x1e000)   # 1 local I/O
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, 0)         # 2 IRQ source
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, 0x1fe000)  # 3 local video ctrl
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, 0x1fe000)  # 4 ext. video ctrl
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, 0x7fe000)  # 5 local video mem.
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, 0x1ffe000) # 6 ISA I/O and mem.
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, 0)         # 7 PCR
 
-               .quad   0xfffffffffffe2000
-               .quad   0x0000029e
-               .quad   0x00000000
-               .word   PM_4K
-               .word   0
-
-# TLB entry 1: PROM
-
-               .quad   0xffffffffe1000000
-               .quad   0x03ffc013
-               .quad   0x00000001              # nonsense ...
-               .word   PM_256K
-               .word   0
-
-# TLB entry 2: local I/O space
-
-               .quad   0xffffffffe0000000
-               .quad   0x02000017
-               .quad   0x00000001              # nonsense ...
-               .word   PM_64K
-               .word   0
-
-# TLB entry 3: DRAM config register
-
-               .quad   0xffffffffe00e0000
-               .quad   0x02003817
-               .quad   0x02003c17
-               .word   PM_64K
-               .word   0
-
-# TLB entry 4: Interrupt source register
-
-               .quad   0xffffffffe0100000
-               .quad   0x03c00017
-               .quad   0x00000001              # nonsense ...
-               .word   PM_4K
-               .word   0
-
-# TLB entry 5: Local video control
-
-               .quad   0xffffffffe0200000
-               .quad   0x01800017
-               .quad   0x01804017
-               .word   PM_1M
-               .word   0
-
-# TLB entry 6: Extended video control
-
-               .quad   0xffffffffe0400000
-               .quad   0x01808017
-               .quad   0x0180c017
-               .word   PM_1M
-               .word   0
-
-# TLB entry 7: Local video memory
-
-               .quad   0xffffffffe0800000
-               .quad   0x01000017
-               .quad   0x01010017
-               .word   PM_4M
-               .word   0
 
-# TLB entry 8: ISA I/O space
-
-               .quad   0xffffffffe2000000
-               .quad   0x02400017
-               .quad   0x02440017
-               .word   PM_16M
-               .word   0
-
-# TLB entry 9: PCR (???)
-
-               .quad   0xffffffffffffe000
-               .quad   0x00000001              # nonsense...
-               .quad   0x0001ffd7
-               .word   PM_4K
-               .word   0
-
-# TLB entry 10: Extended video prom
-
-               .quad   0xffffffff10000000
-               .quad   0x0000141f
-               .quad   0x00000001              # nonsense
-               .word   PM_64K
-               .word   0
-#endif
-
-/*
- * page 0 is made non-existent, so that kernel NULL pointer references get
- * caught. Thus the swapper page directory has been moved to 0x1000
- *
- * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
- * with the introduction of the compressed boot code.  Theoretically,
- * the original design of overlaying the startup code with the swapper
- * page directory is still possible --- it would reduce the size of the kernel
- * by 2-3k.  This would be a good thing to do at some point.....
- */
                        .text
 
                        .org    0x1000
-_swapper_pg_dir                =       0x1000
+                       .globl  swapper_pg_dir
+swapper_pg_dir         =       . + (KSEG1-KSEG0)
+
 /*
  * The page tables are initialized to only 4MB here - the final page
  * tables are set up later depending on memory size.
  */
                        .org    0x2000
-_pg0                   =       0x2000
+                       EXPORT(pg0)
 
                        .org    0x3000
-_empty_bad_page                =       0x3000
+                       EXPORT(empty_bad_page)
 
                        .org    0x4000
-_empty_bad_page_table  =       0x4000
+                       EXPORT(empty_bad_page_table)
 
                        .org    0x5000
-_empty_zero_page       =       0x5000
+                       EXPORT(empty_zero_page)
 
                        .org    0x6000
+                       EXPORT(invalid_pte_table)
 
-#if defined (CONFIG_DESKSTATION_TYNE) && !defined (CONFIG_ACER_PICA_61)
-#if 0
-/*
- * tmp_floppy_area is used by the floppy-driver when DMA cannot
- * reach to a buffer-block. It needs to be aligned, so that it isn't
- * on a 64kB border.
- */
-                       .globl  _tmp_floppy_area
-_tmp_floppy_area:      .fill   1024,1,0
-#endif
-/*
- * floppy_track_buffer is used to buffer one track of floppy data: it
- * has to be separate from the tmp_floppy area, as otherwise a single-
- * sector read/write can mess it up. It can contain one full cylinder (sic) of
- * data (36*2*512 bytes).
- */
-                       .globl  _floppy_track_buffer
-_floppy_track_buffer:  .fill   512*2*36,1,0
-#endif /* defined (CONFIG_DESKSTATION_TYNE) && !defined (CONFIG_ACER_PICA_61) */
-                       .globl  _kernelsp
-_kernelsp:             .word   0
-beepflag:              .word   0
+                       .org    0x7000
+
+                       EXPORT(cache_error_buffer)
+                       .fill   32*4,1,0
+
+                       .data
+                       EXPORT(kernelsp)
+                       PTR     0
index 10697a4c740a2123bbd36bc52bbf628120e52bcc..ff6c0d518f35cfd6b1515566757ae1508877ea20 100644 (file)
@@ -7,50 +7,8 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 
-#define IOTABLE_SIZE 32
-
-typedef struct resource_entry_t {
-       u_long from, num;
-       const char *name;
-       struct resource_entry_t *next;
-} resource_entry_t;
-
-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-static 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;
-       }
-}
-
 /*
- * this changes the io permissions bitmap in the current task.
+ * This changes the io permissions bitmap in the current task.
  */
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
@@ -76,28 +34,3 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx,
 {
        return -ENOSYS;
 }
-
-/*
- * The workhorse function: find where to put a new entry
- */
-static resource_entry_t *find_gap(resource_entry_t *root,
-                                 u_long from, u_long num)
-{
-       unsigned long flags;
-       resource_entry_t *p;
-       
-       if (from > from+num-1)
-               return NULL;
-       save_flags(flags);
-       cli();
-       for (p = root; ; p = p->next) {
-               if ((p != root) && (p->from+p->num-1 >= from)) {
-                       p = NULL;
-                       break;
-               }
-               if ((p->next == NULL) || (p->next->from > from+num-1))
-                       break;
-       }
-       restore_flags(flags);
-       return p;
-}
diff --git a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c
new file mode 100644 (file)
index 0000000..3c156c8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/mips/kernel/ipc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/i386
+ * platform.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+#include <asm/segment.h>
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly;  removing this will need some minor
+ * changes in libc.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+{
+#ifdef CONFIG_SYSVIPC
+       int version;
+
+       version = call >> 16; /* hack for backward compatibility */
+       call &= 0xffff;
+
+       if (call <= SEMCTL)
+               switch (call) {
+               case SEMOP:
+                       return sys_semop (first, (struct sembuf *)ptr, second);
+               case SEMGET:
+                       return sys_semget (first, second, third);
+               case SEMCTL: {
+                       union semun fourth;
+                       int err;
+                       if (!ptr)
+                               return -EINVAL;
+                       if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
+                               return err;
+                       fourth.__pad = (void *) get_fs_long(ptr);
+                       return sys_semctl (first, second, third, fourth);
+                       }
+               default:
+                       return -EINVAL;
+               }
+       if (call <= MSGCTL) 
+               switch (call) {
+               case MSGSND:
+                       return sys_msgsnd (first, (struct msgbuf *) ptr, 
+                                          second, third);
+               case MSGRCV:
+                       switch (version) {
+                       case 0: {
+                               struct ipc_kludge tmp;
+                               int err;
+                               if (!ptr)
+                                       return -EINVAL;
+                               if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
+                                       return err;
+                               memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
+                                              sizeof (tmp));
+                               return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+                               }
+                       case 1: default:
+                               return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+                       }
+               case MSGGET:
+                       return sys_msgget ((key_t) first, second);
+               case MSGCTL:
+                       return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+               default:
+                       return -EINVAL;
+               }
+       if (call <= SHMCTL) 
+               switch (call) {
+               case SHMAT:
+                       switch (version) {
+                       case 0: default: {
+                               ulong raddr;
+                               int err;
+                               if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
+                                       return err;
+                               err = sys_shmat (first, (char *) ptr, second, &raddr);
+                               if (err)
+                                       return err;
+                               put_fs_long (raddr, (ulong *) third);
+                               return 0;
+                               }
+                       case 1: /* iBCS2 emulator entry point */
+                               if (get_fs() != get_ds())
+                                       return -EINVAL;
+                               return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+                       }
+               case SHMDT: 
+                       return sys_shmdt ((char *)ptr);
+               case SHMGET:
+                       return sys_shmget (first, second, third);
+               case SHMCTL:
+                       return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+               default:
+                       return -EINVAL;
+               }
+       return -EINVAL;
+#else /* CONFIG_SYSVIPC */
+       return -ENOSYS;
+#endif /* CONFIG_SYSVIPC */
+}
index 2d0f7f90313b0f0c6177226caf2efdd2ce2d817e..215872c85a3ed573d07b3da8981f79289ea65eb5 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 /*
+ * Mips support by Ralf Baechle and Andreas Busse
+ *
  * The Deskstation Tyne is almost completely like an IBM compatible PC with
  * another type of microprocessor. Therefore this code is almost completely
  * the same. More work needs to be done to support Acer PICA and other
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
+#include <linux/random.h>
 
-#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/bitops.h>
+#include <asm/jazz.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
 
 unsigned char cache_21 = 0xff;
 unsigned char cache_A1 = 0xff;
@@ -117,7 +124,7 @@ int get_irq_list(char *buf)
        for (i = 0 ; i < 16 ; i++, action++) {
                if (!action->handler)
                        continue;
-               len += sprintf(buf+len, "%2d: %8d %c %s\n",
+               len += sprintf(buf+len, "%3d: %8d %c %s\n",
                        i, kstat.interrupts[i],
                        (action->flags & SA_INTERRUPT) ? '+' : ' ',
                        action->name);
@@ -137,6 +144,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
        struct irqaction * action = irq + irq_action;
 
        kstat.interrupts[irq]++;
+       if (action->flags & SA_SAMPLE_RANDOM)
+               add_interrupt_randomness(irq);
        action->handler(irq, regs);
 }
 
@@ -150,6 +159,8 @@ asmlinkage void do_fast_IRQ(int irq)
        struct irqaction * action = irq + irq_action;
 
        kstat.interrupts[irq]++;
+       if (action->flags & SA_SAMPLE_RANDOM)
+               add_interrupt_randomness(irq);
        action->handler(irq, NULL);
 }
 
@@ -168,6 +179,8 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
                return -EBUSY;
        if (!handler)
                return -EINVAL;
+       if (irqflags & SA_SAMPLE_RANDOM)
+               rand_initialize_irq(irq);
        save_flags(flags);
        cli();
        action->handler = handler;
@@ -179,9 +192,9 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
                 * FIXME: Does the SA_INTERRUPT flag make any sense on MIPS???
                 */
                if (action->flags & SA_INTERRUPT)
-                       set_intr_gate(irq,fast_interrupt);
+                       set_int_vector(irq,fast_interrupt);
                else
-                       set_intr_gate(irq,interrupt);
+                       set_int_vector(irq,interrupt);
        }
        if (irq < 8) {
                cache_21 &= ~(1<<irq);
@@ -218,7 +231,7 @@ void free_irq(unsigned int irq)
                cache_A1 |= 1 << (irq-8);
                outb(cache_A1,0xA1);
        }
-       set_intr_gate(irq,bad_interrupt);
+       set_int_vector(irq,bad_interrupt);
        action->handler = NULL;
        action->flags = 0;
        action->mask = 0;
@@ -228,7 +241,7 @@ void free_irq(unsigned int irq)
 
 static void no_action(int cpl, struct pt_regs * regs) { }
 
-unsigned int probe_irq_on (void)
+unsigned long probe_irq_on (void)
 {
        unsigned int i, irqs = 0, irqmask;
        unsigned long delay;
@@ -258,7 +271,7 @@ unsigned int probe_irq_on (void)
        return irqs;
 }
 
-int probe_irq_off (unsigned int irqs)
+int probe_irq_off (unsigned long irqs)
 {
        unsigned int i, irqmask;
 
@@ -284,14 +297,35 @@ void init_IRQ(void)
 {
        int i;
 
-       /* set the clock to 100 Hz */
-       outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
-       outb_p(LATCH & 0xff , 0x40);    /* LSB */
-       outb(LATCH >> 8 , 0x40);        /* MSB */
+       switch (boot_info.machtype) {
+               case MACH_MIPS_MAGNUM_4000:
+               case MACH_ACER_PICA_61:
+                       r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+                                         JAZZ_IE_ETHERNET |
+                                         JAZZ_IE_SERIAL1  |
+                                         JAZZ_IE_SERIAL2  |
+                                         JAZZ_IE_PARALLEL |
+                                         JAZZ_IE_FLOPPY);
+                       r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
+                       set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ1);
+                       /* set the clock to 100 Hz */
+                       r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
+                       break;
+               case MACH_DESKSTATION_TYNE:
+                       /* set the clock to 100 Hz */
+                       outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
+                       outb_p(LATCH & 0xff , 0x40);    /* LSB */
+                       outb(LATCH >> 8 , 0x40);        /* MSB */
+
+                       if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
+                               printk("Unable to get IRQ2 for cascade\n");
+                       break;
+               default:
+                       panic("Unknown machtype in init_IRQ");
+       }
+
        for (i = 0; i < 16 ; i++)
-               set_intr_gate(i, bad_interrupt);
-       if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
-               printk("Unable to get IRQ2 for cascade\n");
+               set_int_vector(i, bad_interrupt);
 
        /* initialize the bottom half routines. */
        for (i = 0; i < 32; i++) {
diff --git a/arch/mips/kernel/jazz-c.c b/arch/mips/kernel/jazz-c.c
new file mode 100644 (file)
index 0000000..608f337
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Jazz specific C parts
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#include <linux/delay.h>
+
+#include <asm/cachectl.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/segment.h>
+
+unsigned char jazz_fd_inb(unsigned int port)
+{
+       unsigned char c;
+
+       c = *(volatile unsigned char *) port;
+       udelay(1);
+
+       return c;
+}
+
+void jazz_fd_outb(unsigned char value, unsigned int port)
+{
+       *(volatile unsigned char *) port = value;
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void)
+{
+       vdma_enable(JAZZ_FLOPPY_DMA);
+}
+
+void jazz_fd_disable_dma(void)
+{
+       vdma_disable(JAZZ_FLOPPY_DMA);
+}
+
+int jazz_fd_request_dma(void)
+{
+       return 0;
+}
+
+void jazz_fd_free_dma(void)
+{
+}
+
+void jazz_fd_clear_dma_ff(void)
+{
+}
+
+void jazz_fd_set_dma_mode(char mode)
+{
+       vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
+}
+
+void jazz_fd_set_dma_addr(unsigned int a)
+{
+       vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
+}
+
+void jazz_fd_set_dma_count(unsigned int count)
+{
+       vdma_set_count(JAZZ_FLOPPY_DMA, count);
+}
+
+int jazz_fd_get_dma_residue(void)
+{
+       return vdma_get_residue(JAZZ_FLOPPY_DMA);
+}
+
+void jazz_fd_enable_irq(void)
+{
+}
+
+void jazz_fd_disable_irq(void)
+{
+}
+
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size)
+{
+       sys_cacheflush((void *)addr, size, DCACHE);
+}
+
+unsigned char jazz_rtc_read_data(void)
+{
+       return *(char *)JAZZ_RTC_BASE;
+}
+
+void jazz_rtc_write_data(unsigned char data)
+{
+       *(char *)JAZZ_RTC_BASE = data;
+}
diff --git a/arch/mips/kernel/jazzdma.c b/arch/mips/kernel/jazzdma.c
new file mode 100644 (file)
index 0000000..2a64831
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * jazzdma.c
+ *
+ * Mips Jazz DMA controller support
+ * (C) 1995 Andreas Busse
+ *
+ * NOTE: Some of the argument checkings could be removed when
+ * things have settled down. Also, instead of returning 0xffffffff
+ * on failure of vdma_alloc() one could leave page #0 unused
+ * and return the more usual NULL pointer as logical address.
+ * 
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/dma.h>
+#include <asm/jazzdma.h>
+
+
+static unsigned long vdma_pagetable_start = 0;
+static unsigned long vdma_pagetable_end = 0;
+
+/*
+ * Debug stuff
+ */
+#define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
+
+static int debuglvl = 3;
+
+/*
+ * Local prototypes
+ */
+static void vdma_pgtbl_init(void);
+
+/*
+ * Initialize the Jazz R4030 dma controller
+ */
+unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
+{
+    /*
+     * Allocate 32k of memory for DMA page tables.
+     * This needs to be page aligned and should be
+     * uncached to avoid cache flushing after every
+     * update.
+     */
+    vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
+    vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
+
+    /*
+     * Clear the R4030 translation table
+     */
+    vdma_pgtbl_init();
+
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    printk("VDMA: R4030 DMA pagetables initialized.\n");
+    return KSEG0ADDR(vdma_pagetable_end);
+}
+
+/*
+ * Allocate DMA pagetables using a simple first-fit algorithm
+ */
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first;
+    int last;
+    int pages;
+    unsigned int frame;
+    unsigned long laddr;
+    int i;
+
+    /* check arguments */
+  
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
+        return VDMA_ERROR;     /* invalid physical address */
+    }
+    if (size > 0x400000 || size == 0)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return VDMA_ERROR;     /* invalid physical address */
+    }
+  
+  /* find free chunk */
+    pages = (size + 4095) >> 12; /* no. of pages to allocate */
+    first = 0;
+    while (1)
+    {
+        while (entry[first].owner != VDMA_PAGE_EMPTY &&
+               first < VDMA_PGTBL_ENTRIES)
+            first++;
+        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
+            return VDMA_ERROR;
+
+        last = first+1;
+        while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
+            last++;
+    
+        if (last-first == pages)
+            break;                     /* found */
+    }
+  
+  /* mark pages as allocated */
+
+    laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+  
+    for (i=first; i<last; i++)
+    {
+        entry[i].frame = frame;
+        entry[i].owner = laddr;
+        frame += VDMA_PAGESIZE;
+    }
+
+    /*
+     * update translation table and
+     * return logical start address
+     */
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    if (vdma_debug > 1)
+        printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
+               pages,laddr);
+
+    if (vdma_debug > 2)
+    {
+        printk("LADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].owner);
+        printk("\n");
+    }
+  
+    return laddr;
+}
+
+/*
+ * Free previously allocated dma translation pages
+ * Note that this does NOT change the translation table,
+ * it just marks the free'd pages as unused!
+ */
+int vdma_free(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int i;
+
+    i = laddr >> 12;
+
+    if (pgtbl[i].owner != laddr)
+    {
+        printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
+               laddr);
+        return -1;
+    }
+  
+    while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
+    {
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        i++;
+    }
+  
+    if (vdma_debug > 1)
+        printk("vdma_free: freed %ld pages starting from %08lx\n",
+               i-(laddr>>12),laddr);
+  
+    return 0;
+}
+
+/*
+ * Map certain page(s) to another physical address.
+ * Caller must have allocated the page(s) before.
+ */
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first;
+    int pages;
+
+    if (laddr > 0xffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid logical address: %08lx\n",laddr);
+        return -EINVAL;                /* invalid logical address */
+    }
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid physical address: %08lx\n",paddr);
+        return -EINVAL;                /* invalid physical address */
+    }
+  
+    pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+    first = laddr >> 12;
+    if (vdma_debug)
+        printk("vdma_remap: first=%x, pages=%x\n",first,pages);
+    if (first+pages > VDMA_PGTBL_ENTRIES)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return -EINVAL;
+    }
+
+    paddr &= ~(VDMA_PAGESIZE-1);
+    while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
+    {
+        if (pgtbl[first].owner != laddr)
+        {
+            if (vdma_debug)
+                printk("Trying to remap other's pages.\n");
+            return -EPERM;             /* not owner */
+        }
+        pgtbl[first].frame = paddr;
+        paddr += VDMA_PAGESIZE;
+        first++;
+        pages--;
+    }
+
+    /* update translation table */
+  
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+  
+    if (vdma_debug > 2)
+    {
+        int i;
+        pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+        first = laddr >> 12;
+        printk("LADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].owner);
+        printk("\n");
+    }
+      
+    return 0;
+}
+
+/*
+ * Translate a physical address to a logical address.
+ * This will return the logical address of the first
+ * match.
+ */
+unsigned long vdma_phys2log(unsigned long paddr)
+{
+    int i;
+    int frame;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        if (pgtbl[i].frame == frame)
+            break;
+    }
+
+    if (i == VDMA_PGTBL_ENTRIES)
+        return 0xffffffff;
+
+    return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
+}
+
+/*
+ * Translate a logical DMA address to a physical address
+ */
+unsigned long vdma_log2phys(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
+}
+  
+/*
+ * Initialize the pagetable with a one-to-one mapping of
+ * the first 16 Mbytes of main memory and declare all
+ * entries to be unused. Using this method will at least
+ * allow some early device driver operations to work.
+ */
+static void vdma_pgtbl_init(void)
+{
+    int i;
+    unsigned long paddr = 0;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+  
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        pgtbl[i].frame = paddr;
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        paddr += VDMA_PAGESIZE;
+    }
+
+/*  vdma_stats(); */
+}
+
+/*
+ * Print DMA statistics
+ */
+void vdma_stats(void)
+{
+    int i;
+  
+    printk("vdma_stats: CONFIG: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_CONFIG));
+    printk("R4030 translation table base: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
+    printk("R4030 translation table limit: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
+    printk("vdma_stats: INV_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_INV_ADDR));
+    printk("vdma_stats: R_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
+    printk("vdma_stats: M_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
+    printk("vdma_stats: IRQ_SOURCE: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
+    printk("vdma_stats: I386_ERROR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_I386_ERROR));
+    printk("vdma_chnl_modes:   ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
+    printk("\n");
+    printk("vdma_chnl_enables: ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
+    printk("\n");
+}
+
+/*
+ * DMA transfer functions
+ */
+
+/*
+ * Enable a DMA channel. Also clear any error conditions.
+ */
+void vdma_enable(int channel)
+{
+    int status;
+  
+    if (vdma_debug)
+        printk("vdma_enable: channel %d\n",channel);
+  
+    /*
+     * Check error conditions first
+     */
+    status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+    if (status & 0x400)
+        printk("VDMA: Channel %d: Address error!\n",channel);
+    if (status & 0x200)
+        printk("VDMA: Channel %d: Memory error!\n",channel);
+
+    /*
+     * Clear all interrupt flags
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
+
+    /*
+     * Enable the desired channel
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                      R4030_CHNL_ENABLE);
+}
+
+/*
+ * Disable a DMA channel
+ */
+void vdma_disable(int channel)
+{
+    if (vdma_debug)
+    {
+        int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+
+        printk("vdma_disable: channel %d\n",channel);
+        printk("VDMA: channel %d status: %04x (%s) mode: "
+               "%02x addr: %06x count: %06x\n",
+               channel,status,((status & 0x600) ? "ERROR" : "OK"),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
+    }
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                      ~R4030_CHNL_ENABLE);
+
+    /*
+     * After disabling a DMA channel a remote bus register should be
+     * read to ensure that the current DMA acknowledge cycle is completed.
+     */
+    *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
+}
+
+/*
+ * Set DMA mode. This function accepts the mode values used
+ * to set a PC-style DMA controller. For the SCSI and FDC
+ * channels, we also set the default modes each time we're
+ * called.
+ * NOTE: The FAST and BURST dma modes are supported by the
+ * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
+ * for now.
+ */
+void vdma_set_mode(int channel, int mode)
+{
+    if (vdma_debug)
+        printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
+
+    switch(channel)
+    {
+    case JAZZ_SCSI_DMA:                        /* scsi */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*                       R4030_MODE_FAST | */
+/*                       R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_16 |
+                          R4030_MODE_ATIME_80);
+        break;
+      
+    case JAZZ_FLOPPY_DMA:      /* floppy */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*                       R4030_MODE_FAST | */
+/*                       R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_8 |
+                          R4030_MODE_ATIME_120);
+        break;
+
+    case JAZZ_AUDIOL_DMA:
+    case JAZZ_AUDIOR_DMA:
+        printk("VDMA: Audio DMA not supported yet.\n");
+        break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
+               channel);
+    }
+  
+    switch(mode)
+    {
+    case DMA_MODE_READ:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                          ~R4030_CHNL_WRITE);
+        break;
+      
+    case DMA_MODE_WRITE:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                          R4030_CHNL_WRITE);
+      break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
+    }
+}
+
+/*
+ * Set Transfer Address
+ */
+void vdma_set_addr(int channel, long addr)
+{
+    if (vdma_debug)
+        printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
+
+    r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
+}
+
+/*
+ * Set Transfer Count
+ */
+void vdma_set_count(int channel, int count)
+{
+    if (vdma_debug)
+        printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
+}
+     
+/*
+ * Get Residual
+ */
+int vdma_get_residue(int channel)
+{
+    int residual;
+  
+    residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
+
+    if (vdma_debug)
+        printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
+  
+    return residual;
+}
diff --git a/arch/mips/kernel/magnum4000.S b/arch/mips/kernel/magnum4000.S
new file mode 100644 (file)
index 0000000..ae176c4
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * arch/mips/kernel/magnum4000.S
+ *
+ * Copyright (C) 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/stackframe.h>
+
+/*
+ * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000 
+ */
+               .set    noreorder
+
+               NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
+               .set    noat
+               SAVE_ALL
+               CLI
+               .set    at
+
+               /*
+                * Get pending interrupts
+                */
+               mfc0    t0,CP0_CAUSE            # get pending interrupts
+               mfc0    t1,CP0_STATUS           # get enabled interrupts
+               and     t0,t1                   # isolate allowed ones
+               andi    t0,0xff00               # isolate pending bits
+               beqz    t0,spurious_interrupt
+               sll     t0,16                   # delay slot
+
+               /*
+                * Find irq with highest priority
+                * FIXME: This is slow
+                */
+               la      t1,ll_vectors
+1:             bltz    t0,2f                   # found pending irq
+               sll     t0,1
+               b       1b
+               subu    t1,PTRSIZE              # delay slot
+
+               /*
+                * Do the low-level stuff
+                */
+2:             lw      t0,(t1)
+               jr      t0
+               nop                             # delay slot
+               END(mips_magnum_4000_handle_int)
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ */
+ll_sw0:                li      s1,~IE_SW0
+               mfc0    t0,CP0_CAUSE
+               and     t0,s1
+               mtc0    t0,CP0_CAUSE
+       PRINT("sw0 received...\n")
+               li      t1,1
+               b       call_real
+               li      t3,PTRSIZE      # delay slot, re-map to irq level 1
+
+ll_sw1:                li      s1,~IE_SW1
+               PANIC("Unimplemented sw1 handler")
+
+ll_local_dma:  li      s1,~IE_IRQ0
+               PANIC("Unimplemented local_dma handler")
+
+ll_local_dev:  lbu     t0,JAZZ_IO_IRQ_SOURCE
+#if __mips == 3
+               dsll    t0,1
+               ld      t0,local_vector(t0)
+#else /* 32 bit */
+               lw      t0,local_vector(t0)
+#endif
+               jr      t0
+               nop
+
+
+loc_no_irq:    PANIC("Unimplemented loc_no_irq handler")
+loc_sound:     PANIC("Unimplemented loc_sound handler")
+loc_video:     PANIC("Unimplemented loc_video handler")
+loc_scsi:      PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard:  li      s1,~JAZZ_IE_KEYBOARD
+               li      t1,JAZZ_KEYBOARD_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_KEYBOARD_IRQ    # delay slot
+
+/*
+ * Ethernet interrupt handler, remapped to level 2
+ */
+loc_ethernet: /*       PRINT ("ethernet IRQ\n"); */
+               li      s1,~JAZZ_IE_ETHERNET
+               li      t1,JAZZ_ETHERNET_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_ETHERNET_IRQ    # delay slot
+
+
+loc_mouse:     PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:   li      s1,~JAZZ_IE_SERIAL1
+               li      t1,JAZZ_SERIAL1_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_SERIAL1_IRQ     # delay slot
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:   li      s1,~JAZZ_IE_SERIAL2
+               li      t1,JAZZ_SERIAL2_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_SERIAL2_IRQ     # delay slot
+
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:  li      s1,~JAZZ_IE_PARALLEL
+               li      t1,JAZZ_PARALLEL_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_PARALLEL_IRQ    # delay slot
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:    li      s1,~JAZZ_IE_FLOPPY
+               li      t1,JAZZ_FLOPPY_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_FLOPPY_IRQ      # delay slot
+
+/*
+ * Now call the real handler
+ */
+loc_call:      lui     s3,%hi(intr_count)
+               lw      t2,%lo(intr_count)(s3)
+               la      t0,IRQ_vectors                  # delay slot
+               addiu   t2,1
+               sw      t2,%lo(intr_count)(s3)
+
+               /*
+                * Temporarily disable interrupt source
+                */
+               lhu     t2,JAZZ_IO_IRQ_ENABLE
+               addu    t0,t3                           # make ptr to IRQ handler
+               lw      t0,(t0)
+               and     t2,s1                           # delay slot
+               sh      t2,JAZZ_IO_IRQ_ENABLE
+               jalr    t0                              # call IRQ handler
+               nor     s1,zero,s1                      # delay slot
+
+               /*
+                * Reenable interrupt
+                */
+               lhu     t2,JAZZ_IO_IRQ_ENABLE
+               lw      t1,%lo(intr_count)(s3)          # delay slot
+               or      t2,s1
+               sh      t2,JAZZ_IO_IRQ_ENABLE
+
+               subu    t1,1
+               jr      v0
+               sw      t1,%lo(intr_count)(s3)
+
+ll_eisa_irq:   li      s1,~IE_IRQ2
+               PANIC("Unimplemented eisa_irq handler")
+
+ll_eisa_nmi:   li      s1,~IE_IRQ3
+               PANIC("Unimplemented eisa_nmi handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to a IBM compatible
+ */
+ll_timer:      lw      t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
+               li      s1,~IE_IRQ4
+               li      t1,0
+               b       call_real
+               li      t3,0            # delay slot, re-map to irq level 0
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count:      j       return
+               mtc0    zero,CP0_COMPARE
+
+/*
+ * Now call the real handler
+ */
+call_real:     lui     s3,%hi(intr_count)
+               lw      t2,%lo(intr_count)(s3)
+               la      t0,IRQ_vectors                  # delay slot
+               addiu   t2,1
+               sw      t2,%lo(intr_count)(s3)
+
+               /*
+                * temporarily disable interrupt
+                */
+               mfc0    t2,CP0_STATUS
+               and     t2,s1
+
+               addu    t0,t3
+               lw      t0,(t0)
+               mtc0    t2,CP0_STATUS           # delay slot
+               jalr    t0
+               nor     s1,zero,s1              # delay slot
+
+               /*
+                * reenable interrupt
+                */
+               mfc0    t2,CP0_STATUS
+               or      t2,s1
+               mtc0    t2,CP0_STATUS
+
+               lw      t2,%lo(intr_count)(s3)
+               subu    t2,1
+
+               jr      v0
+               sw      t2,%lo(intr_count)(s3)
+
+/*
+ * Just for debugging...
+ */
+               LEAF(drawline)
+               li      t1,0xffffffff
+               li      t2,0x100
+1:             sw      t1,(a0)
+               addiu   a0,a0,4
+               addiu   t2,t2,-1
+               bnez    t2,1b
+               nop
+               jr      ra
+               nop
+               END(drawline)
+
+
+               .data
+               PTR     ll_sw0                  # SW0
+               PTR     ll_sw1                  # SW1
+               PTR     ll_local_dma            # Local DMA
+               PTR     ll_local_dev            # Local devices
+               PTR     ll_eisa_irq             # EISA IRQ
+               PTR     ll_eisa_nmi             # EISA NMI
+               PTR     ll_timer                # Timer
+ll_vectors:    PTR     ll_count                # Count/Compare IRQ
+
+local_vector:  PTR     loc_no_irq
+               PTR     loc_parallel
+               PTR     loc_floppy
+               PTR     loc_sound
+               PTR     loc_video
+               PTR     loc_ethernet
+               PTR     loc_scsi
+               PTR     loc_keyboard
+               PTR     loc_mouse
+               PTR     loc_serial1
+               PTR     loc_serial2
+
+               .align  5
+LEAF(spurious_interrupt)
+               /*
+                * Nothing happened... (whistle)
+                */
+               lui     t1,%hi(spurious_count)
+               lw      t0,%lo(spurious_count)(t1)
+               la      v0,return
+               addiu   t0,1
+               jr      ra
+               sw      t0,%lo(spurious_count)(t1)
+               END(spurious_interrupt)
+
diff --git a/arch/mips/kernel/pica.S b/arch/mips/kernel/pica.S
new file mode 100644 (file)
index 0000000..918374f
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * arch/mips/kernel/pica.S
+ *
+ * Copyright (C) 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ *
+ * Acer PICA 61 specific stuff
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/pica.h>
+#include <asm/stackframe.h>
+
+/*
+ * acer_pica_61_handle_int: Interrupt handler for the ACER Pica-61 boards
+ * FIXME: this is *very* experimental!
+ */
+               .set    noreorder
+
+               NESTED(acer_pica_61_handle_int, FR_SIZE, ra)
+               .set    noat
+               SAVE_ALL
+               CLI
+               .set    at
+
+               /*
+                * Get pending interrupts
+                */
+               mfc0    t0,CP0_CAUSE            # get pending interrupts
+               mfc0    t1,CP0_STATUS           # get enabled interrupts
+               and     t0,t1                   # isolate allowed ones
+               andi    t0,0xff00               # isolate pending bits
+               beqz    t0,spurious_interrupt
+               sll     t0,16                   # delay slot
+
+               /*
+                * Find irq with highest priority
+                * FIXME: This is slow - use binary search
+                */
+               la      t1,ll_vectors
+1:             bltz    t0,2f                   # found pending irq
+               sll     t0,1
+               b       1b
+               subu    t1,PTRSIZE              # delay slot
+
+               /*
+                * Do the low-level stuff
+                */
+2:             lw      t0,(t1)
+               jr      t0
+               nop                             # delay slot
+               END(acer_pica_61_handle_int)
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ */
+ll_sw0:                li      s1,~IE_SW0
+               mfc0    t0,CP0_CAUSE
+               and     t0,s1
+               mtc0    t0,CP0_CAUSE
+       PRINT("sw0 received...\n")
+               li      t1,1
+               b       call_real
+               li      t3,PTRSIZE      # delay slot, re-map to irq level 1
+
+ll_sw1:                li      s1,~IE_SW1
+               PANIC("Unimplemented sw1 handler")
+
+ll_local_dma:  li      s1,~IE_IRQ0
+               PANIC("Unimplemented local_dma handler")
+
+ll_local_dev:  lbu     t0,JAZZ_IO_IRQ_SOURCE
+#if __mips == 3
+               dsll    t0,1
+               ld      t0,local_vector(t0)
+#else /* 32 bit */
+               lw      t0,local_vector(t0)
+#endif
+               jr      t0
+               nop
+
+
+loc_no_irq:    PANIC("Unimplemented loc_no_irq handler")
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:  li      s1,~JAZZ_IE_PARALLEL
+               li      t1,JAZZ_PARALLEL_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_PARALLEL_IRQ    # delay slot
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:    li      s1,~JAZZ_IE_FLOPPY
+               li      t1,JAZZ_FLOPPY_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_FLOPPY_IRQ      # delay slot
+
+/*
+ * Now call the real handler
+ */
+loc_call:      lui     s3,%hi(intr_count)
+               lw      t2,%lo(intr_count)(s3)
+               la      t0,IRQ_vectors                  # delay slot
+               addiu   t2,1
+               sw      t2,%lo(intr_count)(s3)
+
+               /*
+                * Temporarily disable interrupt source
+                */
+               lhu     t2,JAZZ_IO_IRQ_ENABLE
+               addu    t0,t3                           # make ptr to IRQ handler
+               lw      t0,(t0)
+               and     t2,s1                           # delay slot
+               sh      t2,JAZZ_IO_IRQ_ENABLE
+               jalr    t0                              # call IRQ handler
+               nor     s1,zero,s1                      # delay slot
+               /*
+                * Reenable interrupt
+                */
+               lhu     t2,JAZZ_IO_IRQ_ENABLE
+               lw      t1,%lo(intr_count)(s3)          # delay slot
+               or      t2,s1
+               sh      t2,JAZZ_IO_IRQ_ENABLE
+               subu    t1,1
+               jr      v0
+               sw      t1,%lo(intr_count)(s3)          # delay slot
+
+ll_isa_irq:    li      s1,~IE_IRQ2
+               PANIC("Unimplemented isa_irq handler")
+
+ll_isa_nmi:    li      s1,~IE_IRQ3
+               PANIC("Unimplemented isa_nmi handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to an IBM compatible
+ */
+ll_timer:      lw      zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
+               li      s1,~IE_IRQ4
+               li      t1,0
+               b       call_real
+               li      t3,0            # delay slot, re-map to irq level 0
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count:      j       return
+               mtc0    zero,CP0_COMPARE
+
+/*
+ * Now call the real handler
+ */
+call_real:     lui     s3,%hi(intr_count)
+               lw      t2,%lo(intr_count)(s3)
+               la      t0,IRQ_vectors
+               addiu   t2,1
+               sw      t2,%lo(intr_count)(s3)
+
+               /*
+                * temporarily disable interrupt
+                */
+               mfc0    t2,CP0_STATUS
+               and     t2,s1
+
+               addu    t0,t3
+               lw      t0,(t0)
+               mtc0    t2,CP0_STATUS           # delay slot
+               jalr    t0
+               nor     s1,zero,s1              # delay slot
+
+               /*
+                * reenable interrupt
+                */
+               mfc0    t2,CP0_STATUS
+               or      t2,s1
+               mtc0    t2,CP0_STATUS
+
+               lw      t2,%lo(intr_count)(s3)
+               subu    t2,1
+
+               jr      v0
+               sw      t2,%lo(intr_count)(s3)
+
+               .data
+               PTR     ll_sw0                  # SW0
+               PTR     ll_sw1                  # SW1
+               PTR     ll_local_dma            # Local DMA
+               PTR     ll_local_dev            # Local devices
+               PTR     ll_isa_irq              # ISA IRQ
+               PTR     ll_isa_nmi              # ISA NMI
+               PTR     ll_timer                # Timer
+ll_vectors:    PTR     ll_count                # Count/Compare IRQ
+
+
+/*
+ * Sound? What sound hardware (whistle) ???
+ */
+loc_sound:     PANIC("Unimplemented loc_sound handler")
+loc_video:     PANIC("Unimplemented loc_video handler")
+
+/*
+ * Ethernet interrupt handler, remapped to level 2
+ */
+loc_ethernet:  li      s1,~JAZZ_IE_ETHERNET
+               li      t1,JAZZ_ETHERNET_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_ETHERNET_IRQ    # delay slot
+
+loc_scsi:      PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard:  li      s1,~JAZZ_IE_KEYBOARD
+               li      t1,JAZZ_KEYBOARD_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_KEYBOARD_IRQ    # re-map to irq level 1
+
+loc_mouse:     PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:   li      s1,~JAZZ_IE_SERIAL1
+               li      t1,JAZZ_SERIAL1_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_SERIAL1_IRQ     # delay slot
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:   li      s1,~JAZZ_IE_SERIAL2
+               li      t1,JAZZ_SERIAL2_IRQ
+               b       loc_call
+               li      t3,PTRSIZE*JAZZ_SERIAL2_IRQ     # delay slot
+
+               .data
+local_vector:  PTR     loc_no_irq
+               PTR     loc_parallel
+               PTR     loc_floppy
+               PTR     loc_sound
+               PTR     loc_video
+               PTR     loc_ethernet
+               PTR     loc_scsi
+               PTR     loc_keyboard
+               PTR     loc_mouse
+               PTR     loc_serial1
+               PTR     loc_serial2
+
+               .align  5
+               .text
+LEAF(spurious_interrupt)
+               /*
+                * Nothing happened... (whistle)
+                */
+               lui     t1,%hi(spurious_count)
+               lw      t0,%lo(spurious_count)(t1)
+               la      v0,return
+               addiu   t0,1
+               jr      ra
+               sw      t0,%lo(spurious_count)(t1)
+               END(spurious_interrupt)
+
index 064942420e6169cf366631a792c09c29b2f500e5..2fc5008bc9b66aca104fbdc98aa070e0728752a1 100644 (file)
@@ -1,14 +1,11 @@
 /*
  *  linux/arch/mips/kernel/process.c
  *
- *  Copyright (C) 1995  Waldorf Electronics,
+ *  Copyright (C) 1995 Ralf Baechle
  *  written by Ralf Baechle
+ *
+ * This file handles the architecture-dependent parts of initialization
  */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
 #include <linux/ldt.h>
+#include <linux/mman.h>
+#include <linux/sys.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 
+#include <asm/bootinfo.h>
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
+#include <asm/processor.h>
 #include <asm/stackframe.h>
+#include <asm/io.h>
 
-asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+asmlinkage void ret_from_sys_call(void);
 
 /*
- * The idle loop on a MIPS..
+ * This routine reboots the machine by asking the keyboard
+ * controller to pulse the reset-line low. We try that for a while,
+ * and if it doesn't work, we do some other stupid things.
+ * Should be ok for Deskstation Tynes. Reseting others needs to be
+ * investigated...
  */
-asmlinkage int sys_idle(void)
+static inline void kb_wait(void)
 {
-#if 0
        int i;
-#endif
 
-       if (current->pid != 0)
-               return -EPERM;
+       for (i=0; i<0x10000; i++)
+               if ((inb_p(0x64) & 0x02) == 0)
+                       break;
+}
 
-#if 0
-       /* Map out the low memory: it's no longer needed */
-       for (i = 0 ; i < 512 ; i++)
-               pgd_clear(swapper_pg_dir + i);
-#endif
+/*
+ * Hard reset for Deskstation Tyne
+ * No hint how this works on Pica boards.
+ */
+void hard_reset_now(void)
+{
+       int i, j;
 
-       /* endless idle loop with no priority at all */
-       current->counter = -100;
+       sti();
        for (;;) {
-               /*
-                * R4[26]00 have wait, R4[04]00 don't.
-                */
-               if (wait_available && !need_resched)
-                       __asm__("wait");
-               schedule();
+               for (i=0; i<100; i++) {
+                       kb_wait();
+                       for(j = 0; j < 100000 ; j++)
+                               /* nothing */;
+                       outb(0xfe,0x64);         /* pulse reset low */
+               }
        }
 }
 
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp)
+void show_regs(struct pt_regs * regs)
 {
-       regs->cp0_epc = eip;
-       regs->reg29 = esp;
+       /*
+        * Saved main processor registers
+        */
+       printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              0, regs->reg1, regs->reg2, regs->reg3,
+               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+       printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg8, regs->reg9, regs->reg10, regs->reg11,
+               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+       printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+              regs->reg16, regs->reg17, regs->reg18, regs->reg19,
+               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+       printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
+              regs->reg24, regs->reg25, regs->reg28, regs->reg29,
+               regs->reg30, regs->reg31);
+
+       /*
+        * Saved cp0 registers
+        */
+       printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
+              regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
 }
 
 /*
@@ -91,89 +114,60 @@ void release_thread(struct task_struct *dead_task)
         * Nothing to do
         */
 }
-
-#define IS_CLONE (regs->orig_reg2 == __NR_clone)
-
-void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
+  
+void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+                 struct task_struct * p, struct pt_regs * regs)
 {
        struct pt_regs * childregs;
+       unsigned long childksp;
 
+       childksp = p->kernel_stack_page + PAGE_SIZE - 8;
        /*
         * set up new TSS
         */
-       p->tss.fs = KERNEL_DS;
-       p->tss.ksp = (p->kernel_stack_page + PAGE_SIZE - 4) | KSEG0;
        childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
-       p->tss.reg29 = ((unsigned long) childregs) | KSEG0; /* new sp */
-       p->tss.reg31 = (unsigned long) ret_from_sys_call;
        *childregs = *regs;
-       childregs->reg2 = 0;
+       childregs->reg2 = 0;            /* Child gets zero as return value */
+       childregs->reg7 = 0;            /* Clear error flag */
+       regs->reg2 = p->pid;
+       if (childregs->cp0_status & ST0_CU0)
+               childregs->reg29 = childksp;
+       else
+               childregs->reg29 = usp;
+       p->tss.ksp = childksp;
+       p->tss.reg29 = (unsigned long) childregs;       /* new sp */
+       p->tss.reg31 = (unsigned long) ret_from_sys_call;
 
        /*
         * New tasks loose permission to use the fpu. This accelerates context
-        * switching for non fp programs, which true for the most programs.
+        * switching for most programs since they don't use the fpu.
         */
-       p->tss.cp0_status = regs->cp0_status &
-                           ~(ST0_CU1|ST0_CU0|ST0_KSU|ST0_ERL|ST0_EXL);
-       childregs->cp0_status &= ~(ST0_CU1|ST0_CU0);
+       p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
+                            ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
+       childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
 }
 
 /*
- * fill in the user structure for a core dump..
+ * fill in the fpu structure for a core dump..
+ *
+ * Actually this is "int dump_fpu (struct elf_fpregset_t *fpu)"
  */
-void dump_thread(struct pt_regs * regs, struct user * dump)
+int dump_fpu (int shutup_the_gcc_warning_about_elf_fpregset_t)
 {
+       int fpvalid = 0;
        /*
-        * Not ready yet
+        * To do...
         */
-#if 0
-       int i;
 
-/* changed the size calculations - should hopefully work better. lbt */
-       dump->magic = CMAGIC;
-       dump->start_code = 0;
-       dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
-       dump->u_tsize = ((unsigned long) current->mm->end_code) >> 12;
-       dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12;
-       dump->u_dsize -= dump->u_tsize;
-       dump->u_ssize = 0;
-       for (i = 0; i < 8; i++)
-               dump->u_debugreg[i] = current->debugreg[i];  
-
-       if (dump->start_stack < TASK_SIZE)
-               dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> 12;
-
-       dump->regs = *regs;
-
-/* Flag indicating the math stuff is valid. We don't support this for the
-   soft-float routines yet */
-       if (hard_math) {
-               if ((dump->u_fpvalid = current->used_math) != 0) {
-                       if (last_task_used_math == current)
-                               __asm__("clts ; fnsave %0": :"m" (dump->i387));
-                       else
-                               memcpy(&dump->i387,&current->tss.i387.hard,sizeof(dump->i387));
-               }
-       } else {
-               /* we should dump the emulator state here, but we need to
-                  convert it into standard 387 format first.. */
-               dump->u_fpvalid = 0;
-       }
-#endif
+       return fpvalid;
 }
 
 /*
- * sys_execve() executes a new program.
+ * fill in the user structure for a core dump..
  */
-asmlinkage int sys_execve(struct pt_regs regs)
+void dump_thread(struct pt_regs * regs, struct user * dump)
 {
-       int error;
-       char * filename;
-
-       error = getname((char *) regs.reg4, &filename);
-       if (error)
-               return error;
-       error = do_execve(filename, (char **) regs.reg5, (char **) regs.reg6, &regs);
-       putname(filename);
-       return error;
+       /*
+        * To do...
+        */
 }
index 4016f6795d8e519f6b175b58506d2cd64e42113c..934507e0509e8923c0bf143b8c4846d6d89cb051 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/user.h>
 
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 
 #if 0
@@ -150,10 +151,8 @@ repeat:
                goto repeat;
        }
 /* this is a hack for non-kernel-mapped video buffers and similar */
-       if (page < high_memory) {
-               page += addr & ~PAGE_MASK;
-               *(unsigned long *) page = data;
-       }
+       if (page < high_memory)
+               *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
        set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -463,6 +462,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                case PTRACE_KILL: {
                        long tmp;
 
+                       if (child->state == TASK_ZOMBIE)        /* already dead */
+                               return 0;
                        wake_up_process(child);
                        child->exit_code = SIGKILL;
        /* make sure the single step bit is not set. */
diff --git a/arch/mips/kernel/r4xx0.S b/arch/mips/kernel/r4xx0.S
new file mode 100644 (file)
index 0000000..88304f4
--- /dev/null
@@ -0,0 +1,829 @@
+/*
+ * arch/mips/kernel/r4xx0.S
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * Written by Ralf Baechle and Andreas Busse
+ *
+ * This file contains most of the R4xx0 specific routines.  Due to the
+ * similarities this should hopefully also be fine for the R10000.  For
+ * now we especially support the R10000 by not invalidating entries out of
+ * the TLB before calling the C handlers.
+ *
+ * This code is evil magic. Read appendix f (coprozessor 0 hazards) of
+ * all R4xx0 manuals and think about that MIPS means "Microprocessor without
+ * Interlocked Pipeline Stages" before you even think about changing this code!
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/segment.h>
+#include <asm/stackframe.h>
+
+#ifdef __SMP__
+#error "Fix this for SMP"
+#else
+#define current current_set
+#endif
+
+MODE_ALIAS     =       0x0016                  # uncachable
+
+               .text
+               .set    mips3
+               .set    noreorder
+
+               .align  5
+               NESTED(handle_tlbl, FR_SIZE, sp)
+               .set    noat
+               /*
+                * Check whether this is a refill or an invalid exception
+                *
+                * NOTE: Some MIPS manuals say that the R4x00 sets the
+                * BadVAddr only when EXL == 0. This is wrong - BadVAddr
+                * is being set for all Reload, Invalid and Modified
+                * exceptions.
+                */
+               mfc0    k0,CP0_BADVADDR
+               mfc0    k1,CP0_ENTRYHI
+               ori     k0,0x1fff
+               xori    k0,0x1fff
+               andi    k1,0xff
+               or      k0,k1
+               mfc0    k1,CP0_ENTRYHI
+               mtc0    k0,CP0_ENTRYHI
+               nop                                     # for R4[04]00 pipeline
+               nop
+               nop
+               tlbp
+               nop                                     # for R4[04]00 pipeline
+               nop
+               mfc0    k0,CP0_INDEX
+               bgez    k0,invalid_tlbl                 # bad addr in c0_badvaddr
+               mtc0    k1,CP0_ENTRYHI                  # delay slot
+               /*
+                * Damn... The next nop is required on my R4400PC V5.0, but
+                * I don't know why - at least there is no documented
+                * reason as for the others :-(
+                */
+               nop
+
+#ifdef CONF_DEBUG_TLB
+               /*
+                * OK, this is a double fault. Let's see whether this is
+                * due to an invalid entry in the page_table.
+                */
+               dmfc0   k0,CP0_BADVADDR
+               srl     k0,12
+               sll     k0,2
+               lui     k1,%HI(TLBMAP)
+               addu    k0,k1
+               lw      k1,(k0)
+               andi    k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
+               bnez    k1,reload_pgd_entries
+               nop                                     # delay slot
+
+               .set    noat
+               SAVE_ALL
+               .set    at
+               PRINT("Double fault caused by invalid entries in pgd:\n")
+               dmfc0   a1,CP0_BADVADDR
+               PRINT("Double fault address     : %08lx\n")
+               dmfc0   a1,CP0_EPC
+               PRINT("c0_epc                   : %08lx\n")
+               jal     show_regs
+               move    a0,sp
+               jal     dump_tlb_all
+               nop
+               dmfc0   a0,CP0_BADVADDR
+               jal     dump_list_current
+               nop
+               .set    noat
+               STI
+               .set    at
+               PANIC("Corrupted pagedir")
+               .set    noat
+
+reload_pgd_entries:
+#endif /* CONF_DEBUG_TLB */
+
+               /*
+                * Load missing pair of entries from the pgd and return.
+                */
+               dmfc0   k1,CP0_CONTEXT
+               dsra    k1,1
+               lwu     k0,(k1)                 # Never causes nested exception
+               lwu     k1,4(k1)
+               dsrl    k0,6                    # Convert to EntryLo format
+               dsrl    k1,6                    # Convert to EntryLo format
+               dmtc0   k0,CP0_ENTRYLO0
+               dmtc0   k1,CP0_ENTRYLO1
+               nop                             # for R4[04]00 pipeline
+               tlbwr
+               nop                             # for R4[04]00 pipeline
+               nop
+               nop
+               /*
+                * We don't know whether the original access was read or
+                * write, so return and see what happens...
+                */
+               eret
+
+               /*
+                * Handle invalid exception
+                *
+                * There are two possible causes for an invalid (tlbl)
+                * exception:
+                * 1) pages with present bit set but the valid bit clear
+                * 2) nonexistant pages
+                * Case one needs fast handling, therefore don't save
+                * registers yet.
+                *
+                * k0 contains c0_index.
+                */
+invalid_tlbl:
+#ifdef CONFIG_TLB_SHUTDOWN
+               /*
+                * Remove entry so we don't need to care later
+                * For sake of the R4000 V2.2 pipeline the tlbwi insn
+                * has been moved down. Moving it around is juggling with
+                * explosives...
+                */
+               lui     k1,0x0008
+               or      k0,k1
+               dsll    k0,13
+               dmtc0   k0,CP0_ENTRYHI
+               dmtc0   zero,CP0_ENTRYLO0
+               dmtc0   zero,CP0_ENTRYLO1
+#endif
+               /*
+                * Test present bit in entry
+                */
+               dmfc0   k0,CP0_BADVADDR
+               srl     k0,12
+               sll     k0,2
+#ifdef CONFIG_TLB_SHUTDOWN
+               tlbwi                                           # do not move!
+#endif
+               lui     k1,%HI(TLBMAP)
+               addu    k0,k1
+               lw      k1,(k0)
+               andi    k1,(_PAGE_PRESENT|_PAGE_READ)
+               xori    k1,(_PAGE_PRESENT|_PAGE_READ)
+               bnez    k1,nopage_tlbl
+               /*
+                * Present and read bits are set -> set valid and accessed bits
+                */
+               lw      k1,(k0)                                 # delay slot
+               ori     k1,(_PAGE_VALID|_PAGE_ACCESSED)
+               sw      k1,(k0)
+               eret
+
+               /*
+                * Page doesn't exist. Lots of work which is less important
+                * for speed needs to be done, so hand it all over to the
+                * kernel memory management routines.
+                */
+nopage_tlbl:   SAVE_ALL
+               dmfc0   a2,CP0_BADVADDR
+               STI
+               .set    at
+               /*
+                * a0 (struct pt_regs *) regs
+                * a1 (unsigned long)    0 for read access
+                * a2 (unsigned long)    faulting virtual address
+                */
+               move    a0,sp
+               jal     do_page_fault
+               li      a1,0                            # delay slot
+               j       ret_from_sys_call
+               nop                                     # delay slot
+               END(handle_tlbl)
+
+               .text
+               .align  5
+               NESTED(handle_tlbs, FR_SIZE, sp)
+               .set    noat
+               /*
+                * It is impossible that is a nested reload exception.
+                * Therefore this must be a invalid exception.
+                * Two possible cases:
+                * 1) Page exists but not dirty.
+                * 2) Page doesn't exist yet. Hand over to the kernel.
+                *
+                * Test whether present bit in entry is set
+                */
+               dmfc0   k0,CP0_BADVADDR
+               srl     k0,12
+               sll     k0,2
+               lui     k1,%HI(TLBMAP)
+               addu    k0,k1
+               lw      k1,(k0)
+               tlbp                                    # find faulting entry
+               andi    k1,(_PAGE_PRESENT|_PAGE_WRITE)
+               xori    k1,(_PAGE_PRESENT|_PAGE_WRITE)
+               bnez    k1,nopage_tlbs
+               /*
+                * Present and writable bits set: set accessed and dirty bits.
+                */
+               lw      k1,(k0)                         # delay slot
+               ori     k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
+                              _PAGE_VALID|_PAGE_DIRTY)
+               sw      k1,(k0)
+               /*
+                * Now reload the entry into the TLB
+                */
+               ori     k0,0x0004
+               xori    k0,0x0004
+               lw      k1,4(k0)
+               lw      k0,(k0)
+               srl     k1,6
+               srl     k0,6
+               dmtc0   k1,CP0_ENTRYLO1
+               dmtc0   k0,CP0_ENTRYLO0
+               nop                             # for R4[04]00 pipeline
+               tlbwi
+               nop                             # for R4[04]00 pipeline
+               nop
+               nop
+               eret
+
+               /*
+                * Page doesn't exist. Lots of work which is less important
+                * for speed needs to be done, so hand it all over to the
+                * kernel memory management routines.
+                */
+nopage_tlbs:
+nowrite_mod:
+#ifdef CONFIG_TLB_SHUTDOWN
+               /*
+                * Remove entry so we don't need to care later
+                */
+               mfc0    k0,CP0_INDEX
+#ifdef CONF_DEBUG_TLB
+               bgez    k0,2f
+               nop
+               /*
+                * We got a tlbs exception but found no matching entry in
+                * the tlb.  This should never happen.  Paranoia makes us
+                * check it, though.
+                */
+               SAVE_ALL
+               jal     show_regs
+               move    a0,sp
+               .set    at
+               mfc0    a1,CP0_BADVADDR
+               PRINT("c0_badvaddr == %08lx\n")
+               mfc0    a1,CP0_INDEX
+               PRINT("c0_index    == %08x\n")
+               mfc0    a1,CP0_ENTRYHI
+               PRINT("c0_entryhi  == %08x\n")
+               .set    noat
+               STI
+               .set    at
+               PANIC("Tlbs or tlbm exception with no matching entry in tlb")
+1:             j       1b
+               nop
+2:
+#endif /* CONF_DEBUG_TLB */
+               lui     k1,0x0008
+               or      k0,k1
+               dsll    k0,13
+               dmtc0   k0,CP0_ENTRYHI
+               dmtc0   zero,CP0_ENTRYLO0
+               dmtc0   zero,CP0_ENTRYLO1
+               nop                             # for R4[04]00 pipeline
+               nop                             # R4000 V2.2 requires 4 NOPs
+               nop
+               nop
+               tlbwi
+#endif
+               .set    noat
+               SAVE_ALL
+               dmfc0   a2,CP0_BADVADDR
+               STI
+               .set    at
+               /*
+                * a0 (struct pt_regs *) regs
+                * a1 (unsigned long)    1 for write access
+                * a2 (unsigned long)    faulting virtual address
+                */
+               move    a0,sp
+               jal     do_page_fault
+               li      a1,1                            # delay slot
+               j       ret_from_sys_call
+               nop                                     # delay slot
+               END(handle_tlbs)
+
+               .align  5
+               NESTED(handle_mod, FR_SIZE, sp)
+               .set    noat
+               /*
+                * Two possible cases:
+                * 1) Page is writable but not dirty -> set dirty and return
+                * 2) Page is not writable -> call C handler
+                */
+               dmfc0   k0,CP0_BADVADDR
+               srl     k0,12
+               sll     k0,2
+               lui     k1,%HI(TLBMAP)
+               addu    k0,k1
+               lw      k1,(k0)
+               tlbp                                    # find faulting entry
+               andi    k1,_PAGE_WRITE
+               beqz    k1,nowrite_mod
+               /*
+                * Present and writable bits set: set accessed and dirty bits.
+                */
+               lw      k1,(k0)                         # delay slot
+               ori     k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
+               sw      k1,(k0)
+               /*
+                * Now reload the entry into the tlb
+                */
+               ori     k0,0x0004
+               xori    k0,0x0004
+               lw      k1,4(k0)
+               lw      k0,(k0)
+               srl     k1,6
+               srl     k0,6
+               dmtc0   k1,CP0_ENTRYLO1
+               dmtc0   k0,CP0_ENTRYLO0
+               nop                             # for R4[04]00 pipeline
+               nop
+               nop
+               tlbwi
+               nop                             # for R4[04]00 pipeline
+               nop
+               nop
+               eret
+               END(handle_mod)
+               .set    at
+
+/*
+ * Until SAVE_ALL/RESTORE_ALL handle registers 64-bit wide we have to
+ * disable interrupts here.
+ */
+               .set    noreorder
+               LEAF(tlbflush)
+               mfc0    t3,CP0_STATUS
+               ori     t4,t3,1
+               xori    t4,1
+               mtc0    t4,CP0_STATUS
+               li      t0,PM_4K
+               mtc0    t0,CP0_PAGEMASK
+               la      t0,boot_info
+               lw      t0,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
+               dmtc0   zero,CP0_ENTRYLO0
+               dmtc0   zero,CP0_ENTRYLO1
+               mfc0    t2,CP0_WIRED
+1:             subu    t0,1
+               mtc0    t0,CP0_INDEX
+               lui     t1,0x0008
+               or      t1,t0,t1
+               dsll    t1,13
+               dmtc0   t1,CP0_ENTRYHI
+               bne     t2,t0,1b
+               tlbwi                                   # delay slot
+               jr      ra
+               mtc0    t3,CP0_STATUS                   # delay slot
+               END(tlbflush)
+
+               /*
+                * Code necessary to switch tasks on an Linux/MIPS machine.
+                */
+               .align  5
+               LEAF(resume)
+               /*
+                * Current task's task_struct
+                */
+               lui     t5,%hi(current)
+               lw      t0,%lo(current)(t5)
+
+               /*
+                * Save status register
+                */
+               mfc0    t1,CP0_STATUS
+               addu    t0,a1                           # Add tss offset
+               sw      t1,TOFF_CP0_STATUS(t0)
+
+               /*
+                * Disable interrupts
+                */
+               ori     t2,t1,0x1f
+               xori    t2,0x1e
+               mtc0    t2,CP0_STATUS
+
+               /*
+                * Save non-scratch registers
+                * All other registers have been saved on the kernel stack
+                */
+               sw      s0,TOFF_REG16(t0)
+               sw      s1,TOFF_REG17(t0)
+               sw      s2,TOFF_REG18(t0)
+               sw      s3,TOFF_REG19(t0)
+               sw      s4,TOFF_REG20(t0)
+               sw      s5,TOFF_REG21(t0)
+               sw      s6,TOFF_REG22(t0)
+               sw      s7,TOFF_REG23(t0)
+               sw      gp,TOFF_REG28(t0)
+               sw      sp,TOFF_REG29(t0)
+               sw      fp,TOFF_REG30(t0)
+
+               /*
+                * Save floating point state
+                */
+               sll     t2,t1,2
+               bgez    t2,2f
+               sw      ra,TOFF_REG31(t0)               # delay slot
+               sll     t2,t1,5
+               bgez    t2,1f
+               sdc1    $f0,(TOFF_FPU+0)(t0)            # delay slot
+               /*
+                * Store the 16 odd double precision registers
+                */
+               sdc1    $f1,(TOFF_FPU+8)(t0)
+               sdc1    $f3,(TOFF_FPU+24)(t0)
+               sdc1    $f5,(TOFF_FPU+40)(t0)
+               sdc1    $f7,(TOFF_FPU+56)(t0)
+               sdc1    $f9,(TOFF_FPU+72)(t0)
+               sdc1    $f11,(TOFF_FPU+88)(t0)
+               sdc1    $f13,(TOFF_FPU+104)(t0)
+               sdc1    $f15,(TOFF_FPU+120)(t0)
+               sdc1    $f17,(TOFF_FPU+136)(t0)
+               sdc1    $f19,(TOFF_FPU+152)(t0)
+               sdc1    $f21,(TOFF_FPU+168)(t0)
+               sdc1    $f23,(TOFF_FPU+184)(t0)
+               sdc1    $f25,(TOFF_FPU+200)(t0)
+               sdc1    $f27,(TOFF_FPU+216)(t0)
+               sdc1    $f29,(TOFF_FPU+232)(t0)
+               sdc1    $f31,(TOFF_FPU+248)(t0)
+
+               /*
+                * Store the 16 even double precision registers
+                */
+1:             cfc1    t1,fcr31
+               sdc1    $f2,(TOFF_FPU+16)(t0)
+               sdc1    $f4,(TOFF_FPU+32)(t0)
+               sdc1    $f6,(TOFF_FPU+48)(t0)
+               sdc1    $f8,(TOFF_FPU+64)(t0)
+               sdc1    $f10,(TOFF_FPU+80)(t0)
+               sdc1    $f12,(TOFF_FPU+96)(t0)
+               sdc1    $f14,(TOFF_FPU+112)(t0)
+               sdc1    $f16,(TOFF_FPU+128)(t0)
+               sdc1    $f18,(TOFF_FPU+144)(t0)
+               sdc1    $f20,(TOFF_FPU+160)(t0)
+               sdc1    $f22,(TOFF_FPU+176)(t0)
+               sdc1    $f24,(TOFF_FPU+192)(t0)
+               sdc1    $f26,(TOFF_FPU+208)(t0)
+               sdc1    $f28,(TOFF_FPU+224)(t0)
+               sdc1    $f30,(TOFF_FPU+240)(t0)
+               sw      t1,(TOFF_FPU+256)(t0)
+
+               /*
+                * Switch current task
+                */
+2:             sw      a0,%lo(current)(t5)
+               addu    a0,a1                   # Add tss offset
+
+               /*
+                * Switch address space
+                */
+
+               /*
+                * (Choose new ASID for process)
+                * This isn't really required, but would speed up
+                * context switching.
+                */
+
+               /*
+                * Switch the root pointer
+                */
+               lw      t0,TOFF_PG_DIR(a0)
+               li      t1,TLB_ROOT
+               mtc0    t1,CP0_ENTRYHI
+               mtc0    zero,CP0_INDEX
+               srl     t0,6
+               ori     t0,MODE_ALIAS
+               mtc0    t0,CP0_ENTRYLO0
+               mtc0    zero,CP0_ENTRYLO1
+               lw      a2,TOFF_CP0_STATUS(a0)
+
+               /*
+                * Flush tlb
+                * (probably not needed, doesn't clobber a0-a3)
+                */
+               jal     tlbflush
+               tlbwi                                   # delay slot
+
+               /*
+                * Restore fpu state:
+                *  - cp0 status register bits
+                *  - fp gp registers
+                *  - cp1 status/control register
+                */
+               ori     t1,a2,1                         # pipeline magic
+               xori    t1,1
+               mtc0    t1,CP0_STATUS
+               sll     t0,a2,2
+               bgez    t0,2f
+               sll     t0,a2,5                         # delay slot
+               bgez    t0,1f
+               ldc1    $f0,(TOFF_FPU+0)(a0)            # delay slot
+               /*
+                * Restore the 16 odd double precision registers only
+                * when enabled in the cp0 status register.
+                */
+               ldc1    $f1,(TOFF_FPU+8)(a0)
+               ldc1    $f3,(TOFF_FPU+24)(a0)
+               ldc1    $f5,(TOFF_FPU+40)(a0)
+               ldc1    $f7,(TOFF_FPU+56)(a0)
+               ldc1    $f9,(TOFF_FPU+72)(a0)
+               ldc1    $f11,(TOFF_FPU+88)(a0)
+               ldc1    $f13,(TOFF_FPU+104)(a0)
+               ldc1    $f15,(TOFF_FPU+120)(a0)
+               ldc1    $f17,(TOFF_FPU+136)(a0)
+               ldc1    $f19,(TOFF_FPU+152)(a0)
+               ldc1    $f21,(TOFF_FPU+168)(a0)
+               ldc1    $f23,(TOFF_FPU+184)(a0)
+               ldc1    $f25,(TOFF_FPU+200)(a0)
+               ldc1    $f27,(TOFF_FPU+216)(a0)
+               ldc1    $f29,(TOFF_FPU+232)(a0)
+               ldc1    $f31,(TOFF_FPU+248)(a0)
+
+               /*
+                * Restore the 16 even double precision registers
+                * when cp1 was enabled in the cp0 status register.
+                */
+1:             lw      t0,(TOFF_FPU+256)(a0)
+               ldc1    $f2,(TOFF_FPU+16)(a0)
+               ldc1    $f4,(TOFF_FPU+32)(a0)
+               ldc1    $f6,(TOFF_FPU+48)(a0)
+               ldc1    $f8,(TOFF_FPU+64)(a0)
+               ldc1    $f10,(TOFF_FPU+80)(a0)
+               ldc1    $f12,(TOFF_FPU+96)(a0)
+               ldc1    $f14,(TOFF_FPU+112)(a0)
+               ldc1    $f16,(TOFF_FPU+128)(a0)
+               ldc1    $f18,(TOFF_FPU+144)(a0)
+               ldc1    $f20,(TOFF_FPU+160)(a0)
+               ldc1    $f22,(TOFF_FPU+176)(a0)
+               ldc1    $f24,(TOFF_FPU+192)(a0)
+               ldc1    $f26,(TOFF_FPU+208)(a0)
+               ldc1    $f28,(TOFF_FPU+224)(a0)
+               ldc1    $f30,(TOFF_FPU+240)(a0)
+               ctc1    t0,fcr31
+
+               /*
+                * Restore non-scratch registers
+                */
+2:             lw      s0,TOFF_REG16(a0)
+               lw      s1,TOFF_REG17(a0)
+               lw      s2,TOFF_REG18(a0)
+               lw      s3,TOFF_REG19(a0)
+               lw      s4,TOFF_REG20(a0)
+               lw      s5,TOFF_REG21(a0)
+               lw      s6,TOFF_REG22(a0)
+               lw      s7,TOFF_REG23(a0)
+               lw      gp,TOFF_REG28(a0)
+               lw      sp,TOFF_REG29(a0)
+               lw      fp,TOFF_REG30(a0)
+               lw      ra,TOFF_REG31(a0)
+
+               /*
+                * Restore status register
+                */
+               lw      t0,TOFF_KSP(a0)
+               sw      t0,kernelsp
+
+               jr      ra
+               mtc0    a2,CP0_STATUS                   # delay slot
+               END(resume)
+
+               /*
+                * Load a new root pointer into the tlb
+                */
+               .set    noreorder
+               LEAF(load_pgd)
+               /*
+                * Switch the root pointer
+                */
+               mfc0    t0,CP0_STATUS
+               ori     t1,t0,1
+               xori    t1,1
+               mtc0    t1,CP0_STATUS
+               srl     a0,6
+               ori     a0,MODE_ALIAS
+               li      t1,TLB_ROOT
+               mtc0    t1,CP0_ENTRYHI
+               mtc0    zero,CP0_INDEX
+               mtc0    a0,CP0_ENTRYLO0
+               mtc0    zero,CP0_ENTRYLO1
+               mtc0    t0,CP0_STATUS
+               j       tlbflush
+               tlbwi                                   # delay slot
+               END(load_pgd)
+
+/*
+ * Some bits in the config register
+ */
+#define CONFIG_DB       (1<<4)
+#define CONFIG_IB       (1<<5)
+
+/*
+ * Flush instruction/data caches
+ *
+ * Parameters: a0 - starting address to flush
+ *             a1 - size of area to be flushed
+ *             a2 - which caches to be flushed
+ *
+ * FIXME:      - ignores parameters in a0/a1
+ *             - doesn't know about second level caches
+ */
+               .set    noreorder
+               LEAF(sys_cacheflush)
+               andi    t1,a2,DCACHE
+               beqz    t1,do_icache
+               li      t0,KSEG0                        # delay slot
+
+               /*
+                * Writeback data cache, even lines
+                */
+               li      t1,CACHELINES-1
+1:             cache   Index_Writeback_Inv_D,0(t0)
+               cache   Index_Writeback_Inv_D,32(t0)
+               cache   Index_Writeback_Inv_D,64(t0)
+               cache   Index_Writeback_Inv_D,96(t0)
+               cache   Index_Writeback_Inv_D,128(t0)
+               cache   Index_Writeback_Inv_D,160(t0)
+               cache   Index_Writeback_Inv_D,192(t0)
+               cache   Index_Writeback_Inv_D,224(t0)
+               cache   Index_Writeback_Inv_D,256(t0)
+               cache   Index_Writeback_Inv_D,288(t0)
+               cache   Index_Writeback_Inv_D,320(t0)
+               cache   Index_Writeback_Inv_D,352(t0)
+               cache   Index_Writeback_Inv_D,384(t0)
+               cache   Index_Writeback_Inv_D,416(t0)
+               cache   Index_Writeback_Inv_D,448(t0)
+               cache   Index_Writeback_Inv_D,480(t0)
+               addiu   t0,512
+               bnez    t1,1b
+               subu    t1,1
+
+               /*
+                * Writeback data cache, odd lines
+                * Only needed for 16 byte line size
+                */
+               mfc0    t1,CP0_CONFIG
+               andi    t1,CONFIG_DB
+               bnez    t1,do_icache
+               li      t1,CACHELINES-1
+1:             cache   Index_Writeback_Inv_D,16(t0)
+               cache   Index_Writeback_Inv_D,48(t0)
+               cache   Index_Writeback_Inv_D,80(t0)
+               cache   Index_Writeback_Inv_D,112(t0)
+               cache   Index_Writeback_Inv_D,144(t0)
+               cache   Index_Writeback_Inv_D,176(t0)
+               cache   Index_Writeback_Inv_D,208(t0)
+               cache   Index_Writeback_Inv_D,240(t0)
+               cache   Index_Writeback_Inv_D,272(t0)
+               cache   Index_Writeback_Inv_D,304(t0)
+               cache   Index_Writeback_Inv_D,336(t0)
+               cache   Index_Writeback_Inv_D,368(t0)
+               cache   Index_Writeback_Inv_D,400(t0)
+               cache   Index_Writeback_Inv_D,432(t0)
+               cache   Index_Writeback_Inv_D,464(t0)
+               cache   Index_Writeback_Inv_D,496(t0)
+               addiu   t0,512
+               bnez    t1,1b
+               subu    t1,1
+
+do_icache:     andi    t1,a2,ICACHE
+               beqz    t1,done
+
+               /*
+                * Flush instruction cache, even lines
+                */
+               lui     t0,0x8000
+               li      t1,CACHELINES-1
+1:             cache   Index_Invalidate_I,0(t0)        
+               cache   Index_Invalidate_I,32(t0)
+               cache   Index_Invalidate_I,64(t0)
+               cache   Index_Invalidate_I,96(t0)
+               cache   Index_Invalidate_I,128(t0)
+               cache   Index_Invalidate_I,160(t0)
+               cache   Index_Invalidate_I,192(t0)
+               cache   Index_Invalidate_I,224(t0)
+               cache   Index_Invalidate_I,256(t0)
+               cache   Index_Invalidate_I,288(t0)
+               cache   Index_Invalidate_I,320(t0)
+               cache   Index_Invalidate_I,352(t0)
+               cache   Index_Invalidate_I,384(t0)
+               cache   Index_Invalidate_I,416(t0)
+               cache   Index_Invalidate_I,448(t0)
+               cache   Index_Invalidate_I,480(t0)
+               addiu   t0,512
+               bnez    t1,1b
+               subu    t1,1
+
+               /*
+                * Flush instruction cache, even lines
+                * Only needed for 16 byte line size
+                */
+               mfc0    t1,CP0_CONFIG
+               andi    t1,CONFIG_IB
+               bnez    t1,done
+               li      t1,CACHELINES-1
+1:             cache   Index_Invalidate_I,16(t0)
+               cache   Index_Invalidate_I,48(t0)
+               cache   Index_Invalidate_I,80(t0)
+               cache   Index_Invalidate_I,112(t0)
+               cache   Index_Invalidate_I,144(t0)
+               cache   Index_Invalidate_I,176(t0)
+               cache   Index_Invalidate_I,208(t0)
+               cache   Index_Invalidate_I,240(t0)
+               cache   Index_Invalidate_I,272(t0)
+               cache   Index_Invalidate_I,304(t0)
+               cache   Index_Invalidate_I,336(t0)
+               cache   Index_Invalidate_I,368(t0)
+               cache   Index_Invalidate_I,400(t0)
+               cache   Index_Invalidate_I,432(t0)
+               cache   Index_Invalidate_I,464(t0)
+               cache   Index_Invalidate_I,496(t0)
+               addiu   t0,512
+               bnez    t1,1b
+               subu    t1,1
+
+done:          j       ra
+               nop
+               END(sys_cacheflush)
+
+/*
+ * Update the TLB - or how instruction scheduling makes code unreadable ...
+ *
+ * MIPS doesn't need any external MMU info: the kernel page tables contain
+ * all the necessary information.  We use this hook though to load the
+ * TLB as early as possible with uptodate information avoiding unecessary
+ * exceptions.
+ *
+ * Parameters: a0 - struct vm_area_struct *vma (ignored)
+ *             a1 - unsigned long address
+ *             a2 - pte_t pte
+ */
+               .set    noreorder
+               LEAF(update_mmu_cache)
+               /*
+                * Step 1: Wipe out old TLB information.  Not shure if
+                * we really need that step; call it paranoia ...
+                * In order to do that we need to disable interrupts.
+                */
+               mfc0    t0,CP0_STATUS           # interrupts off
+               ori     t1,t0,1
+               xori    t1,1
+               mtc0    t1,CP0_STATUS
+               li      t3,TLBMAP               # then wait 3 cycles
+               ori     t1,a1,0xfff             # mask off low 12 bits
+               xori    t1,0xfff
+               mfc0    t2,CP0_ENTRYHI          # copy ASID into address
+               andi    t2,0xff
+               or      t2,t1
+               mtc0    t2,CP0_ENTRYHI
+               srl     t4,a1,12                # wait again three cycles
+               sll     t4,t4,PTRLOG
+               dmtc0   zero,CP0_ENTRYLO0
+               tlbp                            # now query the TLB
+               addu    t3,t4                   # wait another three cycles
+               ori     t3,0xffff
+               xori    t3,0xffff
+               mfc0    t1,CP0_INDEX
+               bltz    t1,1f                   # No old entry?
+               dmtc0   zero,CP0_ENTRYLO1
+               or      t3,t1                   # wait one cycle
+               tlbwi
+               /*
+                * But there still might be a entry for the pgd ...
+                */
+1:             mtc0    t3,CP0_ENTRYHI
+               nop                             # wait 3 cycles
+               nop
+               nop
+               tlbp                            # TLB lookup
+               nop
+               nop
+               mfc0    t1,CP0_INDEX            # wait 3 cycles
+               bltz    t1,1f                   # No old entry?
+               nop             
+               tlbwi                           # gotcha ...
+               /*
+                * Step 2: Reload the TLB with new information.  We can skip
+                * this but this should speed the mess a bit by avoiding
+                * tlbl/tlbs exceptions. (To be done)
+                */
+1:             jr      ra
+               mtc0    t0,CP0_STATUS           # delay slot
+               END(update_mmu_cache)
diff --git a/arch/mips/kernel/resume.S b/arch/mips/kernel/resume.S
deleted file mode 100644 (file)
index 9191c50..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- *  linux/kernel/mips/sys_call.S
- *
- *  Copyright (C) 1994, 1995 Waldorf Electronics
- *  written by Ralf Baechle
- */
-
-/*
- * sys_call.S  contains the system-call and fault low-level handling routines.
- * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
- */
-
-#include <asm/regdef.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-
-/*
- * These are offsets into the task-struct.
- */
-state          =  0
-counter                =  4
-priority       =  8
-signal         = 12
-blocked                = 16
-flags          = 20
-errno          = 24                    #/* MIPS OK */
-exec_domain    = 60                    #/* ??? */
-
-ENOSYS         = 38
-
-/*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- */
-MODE_ALIAS     =       0x0016                  # uncachable
-
-               .text
-               .set    noreorder
-               .set    at
-
-               .globl  _resume
-_resume:
-               /*
-                * current task's task_struct
-                */
-               lui     t5,%hi(_current)
-               lw      t0,%lo(_current)(t5)
-
-               /*
-                * Save status register
-                */
-               mfc0    t1,CP0_STATUS
-               addu    t0,a1                   # Add tss offset
-               sw      t1,TOFF_CP0_STATUS(t0)
-
-               /*
-                * Disable interrupts
-                */
-               ori     t2,t1,0x1f
-               xori    t2,0x1e
-               mtc0    t2,CP0_STATUS
-
-               /*
-                * Save non-scratch registers
-                * All other registers have been saved on the kernel stack
-                */
-               sw      s0,TOFF_REG16(t0)
-               sw      s1,TOFF_REG17(t0)
-               sw      s2,TOFF_REG18(t0)
-               sw      s3,TOFF_REG19(t0)
-               sw      s4,TOFF_REG20(t0)
-               sw      s5,TOFF_REG21(t0)
-               sw      s6,TOFF_REG22(t0)
-               sw      s7,TOFF_REG23(t0)
-               sw      gp,TOFF_REG28(t0)
-               sw      sp,TOFF_REG29(t0)
-               sw      fp,TOFF_REG30(t0)
-               sw      ra,TOFF_REG31(t0)
-
-               /*
-                * Save floating point state
-                */
-               srl     t2,t1,29
-               andi    t2,1
-               beqz    t2,2f
-               srl     t2,t1,26
-               andi    t2,1
-               beqz    t2,1f
-               sdc1    $f0,(TOFF_FPU+0)(t0)    # delay slot
-               /*
-                * Store the 16 odd double precision registers
-                */
-               sdc1    $f1,(TOFF_FPU+8)(t0)
-               sdc1    $f3,(TOFF_FPU+24)(t0)
-               sdc1    $f5,(TOFF_FPU+40)(t0)
-               sdc1    $f7,(TOFF_FPU+56)(t0)
-               sdc1    $f9,(TOFF_FPU+72)(t0)
-               sdc1    $f11,(TOFF_FPU+88)(t0)
-               sdc1    $f13,(TOFF_FPU+104)(t0)
-               sdc1    $f15,(TOFF_FPU+120)(t0)
-               sdc1    $f17,(TOFF_FPU+136)(t0)
-               sdc1    $f19,(TOFF_FPU+152)(t0)
-               sdc1    $f21,(TOFF_FPU+168)(t0)
-               sdc1    $f23,(TOFF_FPU+184)(t0)
-               sdc1    $f25,(TOFF_FPU+200)(t0)
-               sdc1    $f27,(TOFF_FPU+216)(t0)
-               sdc1    $f29,(TOFF_FPU+232)(t0)
-               sdc1    $f31,(TOFF_FPU+248)(t0)
-
-               /*
-                * Store the 16 even double precision registers
-                */
-1:             cfc1    t1,$31
-               sdc1    $f2,(TOFF_FPU+16)(t0)
-               sdc1    $f4,(TOFF_FPU+32)(t0)
-               sdc1    $f6,(TOFF_FPU+48)(t0)
-               sdc1    $f8,(TOFF_FPU+64)(t0)
-               sdc1    $f10,(TOFF_FPU+80)(t0)
-               sdc1    $f12,(TOFF_FPU+96)(t0)
-               sdc1    $f14,(TOFF_FPU+112)(t0)
-               sdc1    $f16,(TOFF_FPU+128)(t0)
-               sdc1    $f18,(TOFF_FPU+144)(t0)
-               sdc1    $f20,(TOFF_FPU+160)(t0)
-               sdc1    $f22,(TOFF_FPU+176)(t0)
-               sdc1    $f24,(TOFF_FPU+192)(t0)
-               sdc1    $f26,(TOFF_FPU+208)(t0)
-               sdc1    $f28,(TOFF_FPU+224)(t0)
-               sdc1    $f30,(TOFF_FPU+240)(t0)
-               sw      t1,(TOFF_FPU+256)(t0)
-
-               /*
-                * Switch current task
-                */
-2:             sw      a0,%lo(_current)(t5)
-               addu    a0,a1                   # Add tss offset
-
-               /*
-                * Switch address space
-                */
-
-               /*
-                * (Choose new ASID for process)
-                */
-
-               /*
-                * Switch the root pointer
-                */
-               lw      t0,TOFF_PG_DIR(a0)
-               la      t1,TLB_ROOT
-               mtc0    t1,CP0_ENTRYHI
-               mtc0    zero,CP0_INDEX
-               srl     t0,6
-               ori     t0,MODE_ALIAS
-               mtc0    t0,CP0_ENTRYLO0
-               mtc0    zero,CP0_ENTRYLO1
-               tlbwi
-
-               /*
-                * Flush tlb (probably not needed)
-                * (Doesn't clobber a0-a3)
-                */
-               jal     _tlbflush
-               nop                                     # delay slot
-
-               lw      a2,TOFF_CP0_STATUS(a0)
-
-               /*
-                * Restore fpu state:
-                *  - cp0 status register bits
-                *  - fp gp registers
-                *  - cp1 status/control register
-                */
-               ori     t1,a2,1                         # pipeline magic
-               xori    t1,1
-               mtc0    t1,CP0_STATUS
-               srl     t0,a2,29
-               andi    t0,1
-               beqz    t0,2f
-               srl     t0,a2,26
-               andi    t0,1
-               beqz    t0,1f
-               ldc1    $f0,(TOFF_FPU+0)(a0)    # delay slot
-               /*
-                * Restore the 16 odd double precision registers only
-                * when enabled in the cp0 status register.
-                */
-               ldc1    $f1,(TOFF_FPU+8)(a0)
-               ldc1    $f3,(TOFF_FPU+24)(a0)
-               ldc1    $f5,(TOFF_FPU+40)(a0)
-               ldc1    $f7,(TOFF_FPU+56)(a0)
-               ldc1    $f9,(TOFF_FPU+72)(a0)
-               ldc1    $f11,(TOFF_FPU+88)(a0)
-               ldc1    $f13,(TOFF_FPU+104)(a0)
-               ldc1    $f15,(TOFF_FPU+120)(a0)
-               ldc1    $f17,(TOFF_FPU+136)(a0)
-               ldc1    $f19,(TOFF_FPU+152)(a0)
-               ldc1    $f21,(TOFF_FPU+168)(a0)
-               ldc1    $f23,(TOFF_FPU+184)(a0)
-               ldc1    $f25,(TOFF_FPU+200)(a0)
-               ldc1    $f27,(TOFF_FPU+216)(a0)
-               ldc1    $f29,(TOFF_FPU+232)(a0)
-               ldc1    $f31,(TOFF_FPU+248)(a0)
-
-               /*
-                * Restore the 16 even double precision registers always
-                * when cp1 was enabled in the cp0 status register.
-                */
-1:             lw      t0,(TOFF_FPU+256)(a0)
-               ldc1    $f2,(TOFF_FPU+16)(a0)
-               ldc1    $f4,(TOFF_FPU+32)(a0)
-               ldc1    $f6,(TOFF_FPU+48)(a0)
-               ldc1    $f8,(TOFF_FPU+64)(a0)
-               ldc1    $f10,(TOFF_FPU+80)(a0)
-               ldc1    $f12,(TOFF_FPU+96)(a0)
-               ldc1    $f14,(TOFF_FPU+112)(a0)
-               ldc1    $f16,(TOFF_FPU+128)(a0)
-               ldc1    $f18,(TOFF_FPU+144)(a0)
-               ldc1    $f20,(TOFF_FPU+160)(a0)
-               ldc1    $f22,(TOFF_FPU+176)(a0)
-               ldc1    $f24,(TOFF_FPU+192)(a0)
-               ldc1    $f26,(TOFF_FPU+208)(a0)
-               ldc1    $f28,(TOFF_FPU+224)(a0)
-               ldc1    $f30,(TOFF_FPU+240)(a0)
-               ctc1    t0,$31
-
-               /*
-                * Restore non-scratch registers
-                */
-2:             lw      s0,TOFF_REG16(a0)
-               lw      s1,TOFF_REG17(a0)
-               lw      s2,TOFF_REG18(a0)
-               lw      s3,TOFF_REG19(a0)
-               lw      s4,TOFF_REG20(a0)
-               lw      s5,TOFF_REG21(a0)
-               lw      s6,TOFF_REG22(a0)
-               lw      s7,TOFF_REG23(a0)
-               lw      gp,TOFF_REG28(a0)
-               lw      sp,TOFF_REG29(a0)
-               lw      fp,TOFF_REG30(a0)
-               lw      ra,TOFF_REG31(a0)
-
-               /*
-                * Restore status register
-                */
-               lw      t0,TOFF_KSP(a0)
-               sw      t0,_kernelsp
-
-               jr      ra
-               mtc0    a2,CP0_STATUS                   # delay slot
index c85927bf8f224bfdec66628827a3e1d4234ec400..db3c0da55677974bc80a52062e7739afc0dc0bb4 100644 (file)
@@ -2,13 +2,16 @@
  *  linux/arch/mips/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 1995  Ralf Baechle
  */
-
+#include <linux/config.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
+#include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
 
+#include <asm/asm.h>
 #include <asm/bootinfo.h>
+#include <asm/vector.h>
 #include <asm/segment.h>
+#include <asm/stackframe.h>
 #include <asm/system.h>
 
+/*
+ * How to handle the machine's features
+ */
+struct feature *feature;
+
+#ifdef CONFIG_ACER_PICA_61
+void acer_pica_61_handle_int(void);
+/*
+ * How to access the floppy controller's ports
+ */
+unsigned char jazz_fd_inb(unsigned int port);
+void jazz_fd_outb(unsigned char value, unsigned int port);
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void);
+void jazz_fd_disable_dma(void);
+int jazz_fd_request_dma(void);
+void jazz_fd_free_dma(void);
+void jazz_fd_clear_dma_ff(void);
+void jazz_fd_set_dma_mode(char mode);
+void jazz_fd_set_dma_addr(unsigned int a);
+void jazz_fd_set_dma_count(unsigned int count);
+int jazz_fd_get_dma_residue(void);
+void jazz_fd_enable_irq(void);
+void jazz_fd_disable_irq(void);
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
+/*
+ * How to access the RTC functions.
+ */
+unsigned char jazz_rtc_read_data(void);
+void jazz_rtc_write_data(unsigned char data);
+
+struct feature acer_pica_61_feature = {
+       acer_pica_61_handle_int,
+       /*
+        * How to access the floppy controller's ports
+        */
+       jazz_fd_inb,
+       jazz_fd_outb,
+       /*
+        * How to access the floppy DMA functions.
+        */
+       jazz_fd_enable_dma,
+       jazz_fd_disable_dma,
+       jazz_fd_request_dma,
+       jazz_fd_free_dma,
+       jazz_fd_clear_dma_ff,
+       jazz_fd_set_dma_mode,
+       jazz_fd_set_dma_addr,
+       jazz_fd_set_dma_count,
+       jazz_fd_get_dma_residue,
+       jazz_fd_enable_irq,
+       jazz_fd_disable_irq,
+       jazz_fd_cacheflush,
+       /*
+        * How to access the RTC functions.
+        */
+       jazz_rtc_read_data,
+       jazz_rtc_write_data
+};
+#endif
+#ifdef CONFIG_DECSTATION
+void decstation_handle_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature decstation_feature = {
+       decstation_handle_handle_int,
+       isa_inb /* Dummy - dunno how to handle this yet */
+       isa_outb, /* Dummy - dunno how to handle this yet */
+};
+#endif
+#ifdef CONFIG_DESKSTATION_RPC44
+void deskstation_rpc44_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature deskstation_rpc44_feature = {
+       deskstation_rpc44_handle_int,
+       isa_inb
+       isa_outb,
+};
+#endif
+#ifdef CONFIG_DESKSTATION_TYNE
+void deskstation_tyne_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature deskstation_tyne_feature = {
+       deskstation_tyne_handle_int,
+       isa_inb,
+       isa_outb,
+};
+#endif
+#ifdef CONFIG_MIPS_MAGNUM_4000
+void mips_magnum_4000_handle_int(void);
+/*
+ * How to access the floppy controller's ports
+ */
+unsigned char jazz_fd_inb(unsigned int port);
+void jazz_fd_outb(unsigned char value, unsigned int port);
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void);
+void jazz_fd_disable_dma(void);
+int jazz_fd_request_dma(void);
+void jazz_fd_free_dma(void);
+void jazz_fd_clear_dma_ff(void);
+void jazz_fd_set_dma_mode(char mode);
+void jazz_fd_set_dma_addr(unsigned int a);
+void jazz_fd_set_dma_count(unsigned int count);
+int jazz_fd_get_dma_residue(void);
+void jazz_fd_enable_irq(void);
+void jazz_fd_disable_irq(void);
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
+/*
+ * How to access the RTC functions.
+ */
+unsigned char jazz_rtc_read_data(void);
+void jazz_rtc_write_data(unsigned char data);
+
+struct feature mips_magnum_4000_feature = {
+       mips_magnum_4000_handle_int,
+       /*
+        * How to access the floppy controller's ports
+        */
+       jazz_fd_inb,
+       jazz_fd_outb,
+       /*
+        * How to access the floppy DMA functions.
+        */
+       jazz_fd_enable_dma,
+       jazz_fd_disable_dma,
+       jazz_fd_request_dma,
+       jazz_fd_free_dma,
+       jazz_fd_clear_dma_ff,
+       jazz_fd_set_dma_mode,
+       jazz_fd_set_dma_addr,
+       jazz_fd_set_dma_count,
+       jazz_fd_get_dma_residue,
+       jazz_fd_enable_irq,
+       jazz_fd_disable_irq,
+       jazz_fd_cacheflush,
+       /*
+        * How to access the RTC functions.
+        */
+       jazz_rtc_read_data,
+       jazz_rtc_write_data
+};
+#endif
+
 /*
  * Tell us the machine setup..
  */
@@ -35,12 +191,12 @@ int EISA_bus = 0;
  * Setup options
  */
 struct drive_info_struct drive_info;
-struct screen_info screen_info;
+struct screen_info screen_info = SCREEN_INFO;
 
 unsigned char aux_device_present;
 extern int ramdisk_size;
 extern int root_mountflags;
-extern int end;
+extern int _end;
 
 extern char empty_zero_page[PAGE_SIZE];
 
@@ -54,61 +210,137 @@ struct bootinfo boot_info = BOOT_INFO;
  * This is set up by the setup-routine at boot-time
  */
 #define PARAM  empty_zero_page
-#define EXT_MEM (boot_info.memupper)
-#define DRIVE_INFO (boot_info.drive_info)
-#define SCREEN_INFO (screen_info)
-#define MOUNT_ROOT_RDONLY (boot_info.mount_root_rdonly)
-#define RAMDISK_SIZE (boot_info.ramdisk_size)
 #if 0
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #endif
-#define COMMAND_LINE (boot_info.command_line)
 
 static char command_line[CL_SIZE] = { 0, };
 
+#if 0
+/*
+ * Code for easy access to new style bootinfo
+ *
+ * Parameter:  tag      -- taglist entry
+ *
+ * returns  :  (tag *) -- pointer to taglist entry, NULL for not found
+ */
+tag *
+bi_TagFind(enum bi_tag tag)
+{
+       /* TBD */
+       return 0;
+}
+
+/*
+ * Only for taglist creators (bootloaders)
+ *
+ * Parameter:  tag       -- (enum bi_tag) taglist entry
+ *
+ * returns  :  1         -- success
+ *             0         -- failure
+ */
+int
+bi_TagAdd(enum bi_tag tag, unsigned long size, void *tagdata)
+{
+       /* TBD */
+       return 0;
+}
+#endif /* 0 */
+
 void setup_arch(char **cmdline_p,
        unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
        unsigned long memory_start, memory_end;
-       char c = ' ', *to = command_line, *from = COMMAND_LINE;
-       int len = 0;
+
+       switch(boot_info.machtype)
+       {
+#ifdef CONFIG_ACER_PICA_61
+       case MACH_ACER_PICA_61:
+               feature = &acer_pica_61_feature;
+               break;
+#endif
+#ifdef CONFIG_DECSTATION
+       case MACH_DECSTATION:
+               feature = &decstation_feature;
+               break;
+#endif
+#ifdef CONFIG_DESKSTATION_RPC
+       case MACH_DESKSTATION_RPC:
+               feature = &deskstation_rpc44_feature;
+               break;
+#endif
+#ifdef CONFIG_DESKSTATION_TYNE
+       case MACH_DESKSTATION_TYNE:
+               feature = &deskstation_tyne_feature;
+               break;
+#endif
+#ifdef CONFIG_MIPS_MAGNUM_4000
+       case MACH_MIPS_MAGNUM_4000:
+               feature = &mips_magnum_4000_feature;
+               break;
+#endif
+       default:
+               panic("Unsupported architecture");
+       }
 
 #if 0
        ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+#else
+#ifdef CONFIG_BLK_DEV_FD
+       ROOT_DEV = to_kdev_t(0x021c);   /* fd0H1440 */
+#else
+       ROOT_DEV = to_kdev_t(0x0101);   /* ram */ 
 #endif
-       drive_info = DRIVE_INFO;
-       screen_info = SCREEN_INFO;
+/*     ROOT_DEV = to_kdev_t(0x00ff); */        /* NFS */
+#endif
+       memcpy(&drive_info, &boot_info.drive_info, sizeof(drive_info));
 #if 0
        aux_device_present = AUX_DEVICE_INFO;
 #endif
-       memory_end = EXT_MEM;
+       memory_end = boot_info.memupper;
        memory_end &= PAGE_MASK;
-       ramdisk_size = RAMDISK_SIZE;
-       if (MOUNT_ROOT_RDONLY)
+       ramdisk_size = boot_info.ramdisk_size;
+       if (boot_info.mount_root_rdonly)
                root_mountflags |= MS_RDONLY;
-       memory_start = (unsigned long) &end - KERNELBASE;
-
-       for (;;) {
-               if (c == ' ' && *(unsigned long *)from == *(unsigned long *)"mem=") {
-                       memory_end = simple_strtoul(from+4, &from, 0);
-                       if ( *from == 'K' || *from == 'k' ) {
-                               memory_end = memory_end << 10;
-                               from++;
-                       } else if ( *from == 'M' || *from == 'm' ) {
-                               memory_end = memory_end << 20;
-                               from++;
-                       }
-               }
-               c = *(from++);
-               if (!c)
-                       break;
-               if (CL_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       *to = '\0';
+
+       memory_start = (unsigned long) &_end;
+       memory_start += (ramdisk_size << 10);
+
        *cmdline_p = command_line;
        *memory_start_p = memory_start;
        *memory_end_p = memory_end;
+
+#if 0
+       /*
+        * Check that struct pt_regs is defined properly
+        * (Should be optimized away, but gcc 2.6.3 is too bad..)
+        */
+       if (FR_SIZE != sizeof(struct pt_regs) ||
+           FR_SIZE & 7)
+       {
+               panic("Check_definition_of_struct_pt_regs\n");
+       }
+#endif
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ */
+int get_cpuinfo(char *buffer)
+{
+       const char *cpu_name[] = CPU_NAMES;
+       const char *mach_name[] = MACH_NAMES;
+
+       return sprintf(buffer,
+                      "cpu\t\t\t: MIPS\n"
+                      "cpu model\t\t: %s\n"
+                      "system type\t\t: %s\n"
+                      "BogoMIPS\t\t: %lu.%02lu\n",
+
+                      cpu_name[boot_info.cputype < CPU_LAST ? boot_info.cputype : CPU_UNKNOWN],
+                      mach_name[boot_info.machtype < CPU_LAST ? boot_info.machtype : CPU_UNKNOWN],
+                      loops_per_sec / 500000, (loops_per_sec / 5000) % 100);
 }
+#endif /* CONFIG_PROC_FS */
index 58f3fa1d2a9ff498d932d3b0beccef4fe9dedfd3..93167481378d1c489b4b439797ad861bef138257 100644 (file)
@@ -3,7 +3,6 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -13,6 +12,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 
+#include <asm/bitops.h>
 #include <asm/segment.h>
 #include <asm/cachectl.h>
 
@@ -21,6 +21,7 @@
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
 
 /*
  * atomically swap in the new signal mask, and wait for a signal.
@@ -44,127 +45,187 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
 /*
  * This sets regs->reg29 even though we don't actually use sigstacks yet..
  */
-asmlinkage int sys_sigreturn(unsigned long __unused)
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
-       struct sigcontext_struct context;
-       struct pt_regs * regs;
+       struct sigcontext_struct *context;
 
-       regs = (struct pt_regs *) &__unused;
-       if (verify_area(VERIFY_READ, (void *) regs->reg29, sizeof(context)))
+       /*
+        * We don't support fixing ADEL/ADES exceptions for signal stack frames.
+        * No big loss - who doesn't care about the alignment of this stack
+        * really deserves to loose.
+        */
+       context = (struct sigcontext_struct *) regs->reg29;
+       if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
+           (regs->reg29 & 3))
                goto badframe;
-       memcpy_fromfs(&context,(void *) regs->reg29, sizeof(context));
-       current->blocked = context.oldmask & _BLOCKABLE;
-       regs->reg1  = context.sc_at;
-       regs->reg2  = context.sc_v0;
-       regs->reg3  = context.sc_v1;
-       regs->reg4  = context.sc_a0;
-       regs->reg5  = context.sc_a1;
-       regs->reg6  = context.sc_a2;
-       regs->reg7  = context.sc_a3;
-       regs->reg8  = context.sc_t0;
-       regs->reg9  = context.sc_t1;
-       regs->reg10 = context.sc_t2;
-       regs->reg11 = context.sc_t3;
-       regs->reg12 = context.sc_t4;
-       regs->reg13 = context.sc_t5;
-       regs->reg14 = context.sc_t6;
-       regs->reg15 = context.sc_t7;
-       regs->reg16 = context.sc_s0;
-       regs->reg17 = context.sc_s1;
-       regs->reg18 = context.sc_s2;
-       regs->reg19 = context.sc_s3;
-       regs->reg20 = context.sc_s4;
-       regs->reg21 = context.sc_s5;
-       regs->reg22 = context.sc_s6;
-       regs->reg23 = context.sc_s7;
-       regs->reg24 = context.sc_t8;
-       regs->reg25 = context.sc_t9;
+
+       current->blocked = context->sc_oldmask & _BLOCKABLE;
+       regs->reg1  = context->sc_at;
+       regs->reg2  = context->sc_v0;
+       regs->reg3  = context->sc_v1;
+       regs->reg4  = context->sc_a0;
+       regs->reg5  = context->sc_a1;
+       regs->reg6  = context->sc_a2;
+       regs->reg7  = context->sc_a3;
+       regs->reg8  = context->sc_t0;
+       regs->reg9  = context->sc_t1;
+       regs->reg10 = context->sc_t2;
+       regs->reg11 = context->sc_t3;
+       regs->reg12 = context->sc_t4;
+       regs->reg13 = context->sc_t5;
+       regs->reg14 = context->sc_t6;
+       regs->reg15 = context->sc_t7;
+       regs->reg16 = context->sc_s0;
+       regs->reg17 = context->sc_s1;
+       regs->reg18 = context->sc_s2;
+       regs->reg19 = context->sc_s3;
+       regs->reg20 = context->sc_s4;
+       regs->reg21 = context->sc_s5;
+       regs->reg22 = context->sc_s6;
+       regs->reg23 = context->sc_s7;
+       regs->reg24 = context->sc_t8;
+       regs->reg25 = context->sc_t9;
        /*
         * Skip k0/k1
         */
-       regs->reg28 = context.sc_gp;
-       regs->reg29 = context.sc_sp;
-       regs->reg30 = context.sc_fp;
-       regs->reg31 = context.sc_ra;
-       regs->cp0_epc = context.sc_epc;
-       regs->cp0_cause = context.sc_cause;
+       regs->reg28 = context->sc_gp;
+       regs->reg29 = context->sc_sp;
+       regs->reg30 = context->sc_fp;
+       regs->reg31 = context->sc_ra;
+       regs->cp0_epc = context->sc_epc;
+       regs->cp0_cause = context->sc_cause;
 
        /*
         * disable syscall checks
         */
        regs->orig_reg2 = -1;
-       return regs->orig_reg2;
+       return context->sc_v0;
+
 badframe:
        do_exit(SIGSEGV);
 }
 
 /*
  * Set up a signal frame...
+ *
+ * This routine is somewhat complicated by the fact that if the kernel may be
+ * entered by an exception other than a system call; e.g. a bus error or other
+ * "bad" exception.  If this is the case, then *all* the context on the kernel
+ * stack frame must be saved.
+ *
+ * For a large number of exceptions, the stack frame format is the same
+ * as that which will be created when the process traps back to the kernel
+ * when finished executing the signal handler. In this case, nothing
+ * must be done. This information is saved on the user stack and restored
+ * when the signal handler is returned.
+ *
+ * The signal handler will be called with ra pointing to code1 (see below) and
+ * one parameters in a0 (signum).
+ *
+ *     usp ->  [unused]                         ; first free word on stack
+ *             arg save space                   ; 16 bytes argument save space
+ *            code1   (addiu sp,#1-offset)     ; syscall number
+ *            code2   (li v0,__NR_sigreturn)   ; syscall number
+ *            code3   (syscall)                ; do sigreturn(2)
+ *     #1|     at, v0, v1, a0, a1, a2, a3       ; All integer registers
+ *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; except zero, k0 and k1
+ *       |     s0, s1, s2, s3, s4, s5, s6, s7
+ *       |     t8, t9, gp, sp, fp, ra;
+ *       |     epc                              ; old program counter
+ *       |     cause                            ; CP0 cause register
+ *       |     oldmask
  */
-static void setup_frame(struct sigaction * sa, unsigned long ** fp,
+
+struct sc {
+       unsigned long   ass[4];
+       unsigned int    code[4];
+       struct sigcontext_struct scc;
+};
+#define scc_offset ((size_t)&((struct sc *)0)->scc)
+
+static void setup_frame(struct sigaction * sa, struct sc **fp,
                         unsigned long pc, struct pt_regs *regs,
                         int signr, unsigned long oldmask)
 {
-       unsigned long * frame;
+       struct sc *frame;
 
        frame = *fp;
-       frame -= 32;
-       if (verify_area(VERIFY_WRITE,frame,21*4))
-               do_exit(SIGSEGV);
-       /*
-        * set up the "normal" stack seen by the signal handler
-        */
-       put_fs_long(regs->reg1 , frame   );
-       put_fs_long(regs->reg2 , frame+ 1);
-       put_fs_long(regs->reg3 , frame+ 2);
-       put_fs_long(regs->reg4 , frame+ 3);
-       put_fs_long(regs->reg5 , frame+ 4);
-       put_fs_long(regs->reg6 , frame+ 5);
-       put_fs_long(regs->reg7 , frame+ 6);
-       put_fs_long(regs->reg8 , frame+ 7);
-       put_fs_long(regs->reg9 , frame+ 8);
-       put_fs_long(regs->reg10, frame+ 9);
-       put_fs_long(regs->reg11, frame+10);
-       put_fs_long(regs->reg12, frame+11);
-       put_fs_long(regs->reg13, frame+12);
-       put_fs_long(regs->reg14, frame+13);
-       put_fs_long(regs->reg15, frame+14);
-       put_fs_long(regs->reg16, frame+15);
-       put_fs_long(regs->reg17, frame+16);
-       put_fs_long(regs->reg18, frame+17);
-       put_fs_long(regs->reg19, frame+18);
-       put_fs_long(regs->reg20, frame+19);
-       put_fs_long(regs->reg21, frame+20);
-       put_fs_long(regs->reg22, frame+21);
-       put_fs_long(regs->reg23, frame+22);
-       put_fs_long(regs->reg24, frame+23);
-       put_fs_long(regs->reg25, frame+24);
+       frame--;
+
        /*
-        * Don't copy k0/k1
+        * We don't support fixing ADEL/ADES exceptions for signal stack frames.
+        * No big loss - who doesn't care about the alignment of this stack
+        * really deserves to loose.
         */
-       put_fs_long(regs->reg28, frame+25);
-       put_fs_long(regs->reg29, frame+26);
-       put_fs_long(regs->reg30, frame+27);
-       put_fs_long(regs->reg31, frame+28);
-       put_fs_long(pc         , frame+29);
-       put_fs_long(oldmask    , frame+30);
+       if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
+           ((unsigned long)frame & 3))
+               do_exit(SIGSEGV);
+
        /*
-        * set up the return code...
+        * Set up the return code ...
         *
         *         .set    noreorder
-        *         .set    noat
+        *         addiu   sp,24
+        *         li      v0,__NR_sigreturn
         *         syscall
-        *         li      $1,__NR_sigreturn
-        *         .set    at
         *         .set    reorder
         */
-       put_fs_long(0x24010077, frame+31);              /* li   $1,119 */
-       put_fs_long(0x000000c0, frame+32);              /* syscall     */
-       *fp = frame;
+       frame->code[0] = 0x27bd0000 + scc_offset;
+       frame->code[1] = 0x24020000 + __NR_sigreturn;
+       frame->code[2] = 0x0000000c;
+
        /*
-        * Flush caches so the instructions will be correctly executed.
+        * Flush caches so that the instructions will be correctly executed.
         */
-       sys_cacheflush(frame, 32*4, BCACHE);
+       sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
+
+       /*
+        * Set up the "normal" sigcontext_struct
+        */
+       frame->scc.sc_at = regs->reg1;          /* Assembler temporary */
+       frame->scc.sc_v0 = regs->reg2;          /* Result registers */
+       frame->scc.sc_v1 = regs->reg3;
+       frame->scc.sc_a0 = regs->reg4;          /* Argument registers */
+       frame->scc.sc_a1 = regs->reg5;
+       frame->scc.sc_a2 = regs->reg6;
+       frame->scc.sc_a3 = regs->reg7;
+
+       frame->scc.sc_t0 = regs->reg8;          /* Caller saved */
+       frame->scc.sc_t1 = regs->reg9;
+       frame->scc.sc_t2 = regs->reg10;
+       frame->scc.sc_t3 = regs->reg11;
+       frame->scc.sc_t4 = regs->reg12;
+       frame->scc.sc_t5 = regs->reg13;
+       frame->scc.sc_t6 = regs->reg14;
+       frame->scc.sc_t7 = regs->reg15;
+
+       frame->scc.sc_s0 = regs->reg16;         /* Callee saved */
+       frame->scc.sc_s1 = regs->reg17;
+       frame->scc.sc_s2 = regs->reg18;
+       frame->scc.sc_s3 = regs->reg19;
+       frame->scc.sc_s4 = regs->reg20;
+       frame->scc.sc_s5 = regs->reg21;
+       frame->scc.sc_s6 = regs->reg22;
+       frame->scc.sc_s7 = regs->reg23;
+
+       frame->scc.sc_t8 = regs->reg24;         /* Caller saved */
+       frame->scc.sc_t9 = regs->reg25;
+
+       /*
+        * Don't copy k0/k1
+        */
+       frame->scc.sc_gp = regs->reg28;         /* global pointer / s8 */
+       frame->scc.sc_sp = regs->reg29;         /* old stack pointer */
+       frame->scc.sc_fp = regs->reg30;         /* old frame pointer */
+       frame->scc.sc_ra = regs->reg31;         /* old return address */
+
+       frame->scc.sc_epc = regs->cp0_epc;      /* Program counter */
+       frame->scc.sc_cause = regs->cp0_cause;  /* c0_epc register */
+
+       frame->scc.sc_oldmask = oldmask;
+       *fp = frame;
+
+       regs->reg4 = signr;             /* argument for handler */
 }
 
 /*
@@ -180,30 +241,15 @@ 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;
+       struct sc *frame = NULL;
        unsigned long pc = 0;
        unsigned long signr;
        struct sigaction * sa;
 
        while ((signr = current->signal & mask)) {
-               __asm__(".set\tnoreorder\n\t"
-                       ".set\tnoat\n\t"
-                       "li\t%0,31\n"
-                       "1:\tsllv\t$1,%1,%0\n\t"
-                       "bgezl\t$1,1b\n\t"
-                       "subu\t$8,1\n\t"
-                       "subu\t%0,31\n\t"
-                       "subu\t%0,$0,%0\n\t"
-                       "li\t$1,1\n\t"
-                       "sllv\t$1,$1,%0\n\t"
-                       "nor\t$1,$0\n\t"
-                       "xor\t%1,$1\n\t"
-                       ".set\tat\n\t"
-                       ".set\treorder"
-                       :"=r" (signr),"=r" (current->signal)
-                       :"0"  (signr),"1"  (current->signal)
-                       :"$1");
-               sa = current->sigaction + signr;
+               signr = ffz(~signr);
+               clear_bit(signr, &current->signal);
+               sa = current->sig->action + signr;
                signr++;
                if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
@@ -219,7 +265,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                current->signal |= _S(signr);
                                continue;
                        }
-                       sa = current->sigaction + signr - 1;
+                       sa = current->sig->action + signr - 1;
                }
                if (sa->sa_handler == SIG_IGN) {
                        if (signr != SIGCHLD)
@@ -241,14 +287,14 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                        continue;
                                current->state = TASK_STOPPED;
                                current->exit_code = signr;
-                               if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & 
+                               if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
                                                SA_NOCLDSTOP))
                                        notify_parent(current);
                                schedule();
                                continue;
 
                        case SIGQUIT: case SIGILL: case SIGTRAP:
-                       case SIGIOT: case SIGFPE: case SIGSEGV:
+                       case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
                                if (current->binfmt && current->binfmt->core_dump) {
                                        if (current->binfmt->core_dump(signr, regs))
                                                signr |= 0x80;
@@ -271,42 +317,40 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                handler_signal |= 1 << (signr-1);
                mask &= ~sa->sa_mask;
        }
+       /*
+        * Who's code doesn't conform to the restartable syscall convention
+        * dies here!!!  The li instruction, a single machine instruction,
+        * must directly be followed by the syscall instruction.
+        */
        if (regs->orig_reg2 >= 0 &&
            (regs->reg2 == -ERESTARTNOHAND ||
             regs->reg2 == -ERESTARTSYS ||
-            regs->reg2 == -ERESTARTNOINTR)) {
+            regs->reg2 == -ERESTARTNOINTR))
+       {
                regs->reg2 = regs->orig_reg2;
-               regs->cp0_epc -= 4;
+               regs->cp0_epc -= 8;
        }
        if (!handler_signal)            /* no handler will be called - return 0 */
                return 0;
        pc = regs->cp0_epc;
-       frame = (unsigned long *) regs->reg29;
+       frame = (struct sc *) regs->reg29;
        signr = 1;
-       sa = current->sigaction;
+       sa = current->sig->action;
        for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
                if (mask > handler_signal)
                        break;
                if (!(mask & handler_signal))
                        continue;
-               setup_frame(sa,&frame,pc,regs,signr,oldmask);
+               setup_frame(sa, &frame, pc, regs, signr, oldmask);
                pc = (unsigned long) sa->sa_handler;
                if (sa->sa_flags & SA_ONESHOT)
                        sa->sa_handler = NULL;
-               /*
-                * force a kernel-mode page-in of the signal
-                * handler to reduce races
-                */
-               __asm__(".set\tnoat\n\t"
-                       "lwu\t$1,(%0)\n\t"
-                       ".set\tat\n\t"
-                       :
-                       :"r" ((char *) pc)
-                       :"$1");
                current->blocked |= sa->sa_mask;
                oldmask |= sa->sa_mask;
        }
-       regs->reg29 = (unsigned long) frame;
+       regs->reg29 = (unsigned long) frame;            /* Stack pointer */
+       regs->reg31 = (unsigned long) frame->code;      /* Return address */
        regs->cp0_epc = pc;             /* "return" to the first handler */
+
        return 1;
 }
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
new file mode 100644 (file)
index 0000000..e199a0a
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * MIPS specific syscall handling functions and syscalls
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/segment.h>
+#include <asm/signal.h>
+
+extern asmlinkage void syscall_trace(void);
+typedef asmlinkage int (*syscall_t)(void *a0,...);
+extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
+                                  int narg);
+extern syscall_t sys_call_table[];
+extern unsigned char sys_narg_table[];
+
+asmlinkage int sys_pipe(struct pt_regs *regs)
+{
+       int fd[2];
+       int error;
+
+       error = do_pipe(fd);
+       if (error)
+               return error;
+       regs->reg2 = fd[0];
+       regs->reg3 = fd[1];
+       return 0;
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
+                                  int flags, int fd, off_t offset)
+{
+       struct file * file = NULL;
+
+       if (flags & MAP_RENAME) {
+               if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+                       return -EBADF;
+       }
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+       return do_mmap(file, addr, len, prot, flags, offset);
+}
+
+asmlinkage int sys_idle(void)
+{
+       if (current->pid != 0)
+               return -EPERM;
+
+       /* endless idle loop with no priority at all */
+       current->counter = -100;
+       for (;;) {
+               /*
+                * R4[26]00 have wait, R4[04]00 don't.
+                */
+               if (wait_available && !need_resched)
+                       __asm__(".set\tmips3\n\t"
+                               "wait\n\t"
+                               ".set\tmips0\n\t");
+               schedule();
+       }
+}
+
+asmlinkage int sys_fork(struct pt_regs *regs)
+{
+       return do_fork(SIGCHLD, regs->reg29, regs);
+}
+
+asmlinkage int sys_clone(struct pt_regs *regs)
+{
+       unsigned long clone_flags;
+       unsigned long newsp;
+
+       clone_flags = regs->reg4;
+       newsp = regs->reg5;
+       if (!newsp)
+               newsp = regs->reg29;
+       return do_fork(clone_flags, newsp, regs);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(struct pt_regs *regs)
+{
+       int error;
+       char * filename;
+
+       error = getname((char *) regs->reg4, &filename);
+       if (error)
+               return error;
+       error = do_execve(filename, (char **) regs->reg5,
+                         (char **) regs->reg6, regs);
+       putname(filename);
+       return error;
+}
+
+/*
+ * Do the indirect syscall syscall.
+ */
+asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
+                           unsigned long a3, unsigned long a4, unsigned long a5,
+                           unsigned long a6)
+{
+       syscall_t syscall;
+
+       if (a0 > __NR_Linux + __NR_Linux_syscalls)
+               return -ENOSYS;
+
+       syscall = sys_call_table[a0];
+       /*
+        * Prevent stack overflow by recursive
+        * syscall(__NR_syscall, __NR_syscall,...);
+        */
+       if (syscall == (syscall_t) sys_syscall)
+               return -EINVAL;
+
+       if (syscall == NULL)
+               return -ENOSYS;
+
+       return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
+}
+
+void do_sys(struct pt_regs *regs)
+{
+       unsigned long syscallnr, usp;
+       syscall_t syscall;
+       int errno, narg;
+
+       /*
+        * Compute the return address;
+        */
+       if (regs->cp0_cause & CAUSEF_BD)
+       {
+               /*
+                * This syscall is in a branch delay slot.  Since we don't do
+                * branch delay slot handling we would get a process trying
+                * to do syscalls ever and ever again.  So better zap it.
+                */
+               printk("%s: syscall in branch delay slot.\n", current->comm);
+               current->sig->action[SIGILL-1].sa_handler = NULL;
+               current->blocked &= ~(1<<(SIGILL-1));
+               send_sig(SIGILL, current, 1);
+               return;
+       }
+       regs->cp0_epc += 4;
+
+       syscallnr = regs->reg2;
+       if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
+               goto illegal_syscall;
+
+       syscall = sys_call_table[syscallnr];
+       if (syscall == NULL)
+               goto illegal_syscall;
+
+       narg = sys_narg_table[syscallnr];
+       if (narg > 4)
+       {
+               /*
+                * Verify that we can savely get the additional parameters
+                * from the user stack.  Of course I could read the params
+                * from unaligned addresses ...  Consider this a programming
+                * course caliber .45.
+                */
+               usp = regs->reg29;
+               if (usp & 3)
+               {
+                       printk("unaligned usp\n");
+                       send_sig(SIGSEGV, current, 1);
+                       regs->reg2 = EFAULT;
+                       regs->reg7 = 1;
+                       return;
+               }
+               errno = verify_area(VERIFY_READ, (void *) (usp + 16),
+                                   (narg - 4) * sizeof(unsigned long));
+               if (errno < 0)
+                       goto bad_syscall;
+       }
+
+       if ((current->flags & PF_TRACESYS) == 0)
+       {
+               errno = do_syscalls(regs, syscall, narg);
+               if (errno < 0 || current->errno)
+                       goto bad_syscall;
+
+               regs->reg2 = errno;
+               regs->reg7 = 0;
+       }
+       else
+       {
+               syscall_trace();
+
+               errno = do_syscalls(regs, syscall, narg);
+               if (errno < 0 || current->errno)
+               {
+                       regs->reg2 = -errno;
+                       regs->reg7 = 1;
+               }
+               else
+               {
+                       regs->reg2 = errno;
+                       regs->reg7 = 0;
+               }
+
+               syscall_trace();
+       }
+       return;
+
+bad_syscall:
+       regs->reg2 = -errno;
+       regs->reg7 = 1;
+       return;
+illegal_syscall:
+       regs->reg2 = ENOSYS;
+       regs->reg7 = 1;
+       return;
+}
diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
new file mode 100644 (file)
index 0000000..0b65c74
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * List of Linux/MIPS syscalls.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+
+/*
+ * This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts.  Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ *
+ * The binary compatibility calls are still missing in this list.
+ */
+SYS(sys_syscall, 7)                            /* 4000 */
+SYS(sys_exit, 1)
+SYS(sys_fork, 0)
+SYS(sys_read, 3)
+SYS(sys_write, 3)
+SYS(sys_open, 3)                               /* 4005 */
+SYS(sys_close, 3)
+SYS(sys_waitpid, 3)
+SYS(sys_creat, 2)
+SYS(sys_link, 2)
+SYS(sys_unlink, 1)                             /* 4010 */
+SYS(sys_execve, 0)
+SYS(sys_chdir, 1)
+SYS(sys_time, 1)
+SYS(sys_mknod, 3)
+SYS(sys_chmod, 2)                              /* 4015 */
+SYS(sys_chown, 3)
+SYS(sys_break, 0)
+SYS(sys_stat, 2)
+SYS(sys_lseek, 3)
+SYS(sys_getpid, 0)                             /* 4020 */
+SYS(sys_mount, 5)
+SYS(sys_umount, 1)
+SYS(sys_setuid, 1)
+SYS(sys_getuid, 0)
+SYS(sys_stime, 1)                              /* 4025 */
+SYS(sys_ptrace, 4)
+SYS(sys_alarm, 1)
+SYS(sys_fstat, 2)
+SYS(sys_pause, 0)
+SYS(sys_utime, 2)                              /* 4030 */
+SYS(sys_stty, 0)
+SYS(sys_gtty, 0)
+SYS(sys_access, 2)
+SYS(sys_nice, 1)
+SYS(sys_ftime, 0)                              /* 4035 */
+SYS(sys_sync, 0)
+SYS(sys_kill, 2)
+SYS(sys_rename, 2)
+SYS(sys_mkdir, 2)
+SYS(sys_rmdir, 1)                              /* 4040 */
+SYS(sys_dup, 1)
+SYS(sys_pipe, 0)
+SYS(sys_times, 1)
+SYS(sys_prof, 0)
+SYS(sys_brk, 1)                                        /* 4045 */
+SYS(sys_setgid, 1)
+SYS(sys_getgid, 0)
+SYS(sys_signal, 2)
+SYS(sys_geteuid, 0)
+SYS(sys_getegid, 0)                            /* 4050 */
+SYS(sys_acct, 0)
+SYS(sys_phys, 0)
+SYS(sys_lock, 0)
+SYS(sys_ioctl, 3)
+SYS(sys_fcntl, 3)                              /* 4055 */
+SYS(sys_mpx, 2)
+SYS(sys_setpgid, 2)
+SYS(sys_ulimit, 0)
+SYS(sys_olduname, 1)
+SYS(sys_umask, 1)                              /* 4060 */
+SYS(sys_chroot, 1)
+SYS(sys_ustat, 2)
+SYS(sys_dup2, 2)
+SYS(sys_getppid, 0)
+SYS(sys_getpgrp, 0)                            /* 4065 */
+SYS(sys_setsid, 0)
+SYS(sys_sigaction, 3)
+SYS(sys_sgetmask, 0)
+SYS(sys_ssetmask, 1)
+SYS(sys_setreuid, 2)                           /* 4070 */
+SYS(sys_setregid, 2)
+SYS(sys_sigsuspend, 3)
+SYS(sys_sigpending, 1)
+SYS(sys_sethostname, 2)
+SYS(sys_setrlimit, 2)                          /* 4075 */
+SYS(sys_getrlimit, 2)
+SYS(sys_getrusage, 2)
+SYS(sys_gettimeofday, 2)
+SYS(sys_settimeofday, 2)
+SYS(sys_getgroups, 2)                          /* 4080 */
+SYS(sys_setgroups, 2)
+SYS(sys_ni_syscall, 0) /* old_select */
+SYS(sys_symlink, 2)
+SYS(sys_lstat, 2)
+SYS(sys_readlink, 3)                           /* 4085 */
+SYS(sys_uselib, 1)
+SYS(sys_swapon, 2)
+SYS(sys_reboot, 3)
+SYS(old_readdir, 3)
+SYS(sys_mmap, 6)                               /* 4090 */
+SYS(sys_munmap, 2)
+SYS(sys_truncate, 2)
+SYS(sys_ftruncate, 2)
+SYS(sys_fchmod, 2)
+SYS(sys_fchown, 3)                             /* 4095 */
+SYS(sys_getpriority, 2)
+SYS(sys_setpriority, 3)
+SYS(sys_profil, 0)
+SYS(sys_statfs, 2)
+SYS(sys_fstatfs, 2)                            /* 4100 */
+SYS(sys_ioperm, 3)
+SYS(sys_socketcall, 2)
+SYS(sys_syslog, 3)
+SYS(sys_setitimer, 3)
+SYS(sys_getitimer, 2)                          /* 4105 */
+SYS(sys_newstat, 2)
+SYS(sys_newlstat, 2)
+SYS(sys_newfstat, 2)
+SYS(sys_uname, 1)
+SYS(sys_iopl, 0)       /* Well, actually 17 args ... */                                /* 4110 */
+SYS(sys_vhangup, 0)
+SYS(sys_idle, 0)
+SYS(sys_vm86, 1)
+SYS(sys_wait4, 4)
+SYS(sys_swapoff, 1)                            /* 4115 */
+SYS(sys_sysinfo, 1)
+SYS(sys_ipc, 6)
+SYS(sys_fsync, 1)
+SYS(sys_sigreturn, 0)
+SYS(sys_clone, 0)                              /* 4120 */
+SYS(sys_setdomainname, 2)
+SYS(sys_newuname, 1)
+SYS(sys_ni_syscall, 0) /* sys_modify_ldt */
+SYS(sys_adjtimex, 1)
+SYS(sys_mprotect, 3)                           /* 4125 */
+SYS(sys_sigprocmask, 3)
+SYS(sys_create_module, 2)
+SYS(sys_init_module, 5)
+SYS(sys_delete_module, 1)
+SYS(sys_get_kernel_syms, 1)                    /* 4130 */
+SYS(sys_quotactl, 0)
+SYS(sys_getpgid, 1)
+SYS(sys_fchdir, 1)
+SYS(sys_bdflush, 2)
+SYS(sys_sysfs, 3)                              /* 4135 */
+SYS(sys_personality, 1)
+SYS(sys_ni_syscall, 0) /* for afs_syscall */
+SYS(sys_setfsuid, 1)
+SYS(sys_setfsgid, 1)
+SYS(sys_llseek, 5)                             /* 4140 */
+SYS(sys_getdents, 3)
+SYS(sys_select, 5)
+SYS(sys_flock, 2)
+SYS(sys_msync, 3)
+SYS(sys_readv, 3)                              /* 4145 */
+SYS(sys_writev, 3)
+SYS(sys_cacheflush, 3)
+SYS(sys_cachectl, 3)
+SYS(sys_sysmips, 4)
+SYS(sys_setup, 0)                              /* 4150 */
+SYS(sys_getsid, 1)
+SYS(sys_ni_syscall, 0)
+SYS(sys_ni_syscall, 0)
+SYS(sys_mlock, 2)
+SYS(sys_munlock, 2)                            /* 4155 */
+SYS(sys_mlockall, 1)
+SYS(sys_munlockall, 0)
diff --git a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c
new file mode 100644 (file)
index 0000000..07ae26e
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * MIPS specific syscalls
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/utsname.h>
+
+#include <asm/cachectl.h>
+#include <asm/segment.h>
+#include <asm/sysmips.h>
+
+static inline size_t
+strnlen_user(const char *s, size_t count)
+{
+       return strnlen(s, count);
+}
+
+/*
+ * How long a hostname can we get from user space?
+ *  -EFAULT if invalid area or too long
+ *  0 if ok
+ *  >0 EFAULT after xx bytes
+ */
+static inline int
+get_max_hostname(unsigned long address)
+{
+       struct vm_area_struct * vma;
+
+       vma = find_vma(current, address);
+       if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
+               return -EFAULT;
+       address = vma->vm_end - address;
+       if (address > PAGE_SIZE)
+               return 0;
+       if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
+          (vma->vm_next->vm_flags & VM_READ))
+               return 0;
+       return address;
+}
+
+asmlinkage int
+sys_sysmips(int cmd, int arg1, int arg2, int arg3)
+{
+       int     *p;
+       char    *name;
+       int     flags, len, retval = -EINVAL;
+
+       switch(cmd)
+       {
+       case SETNAME:
+               if (!suser())
+                       return -EPERM;
+               name = (char *) arg1;
+               len = get_max_hostname((unsigned long)name);
+               if (retval < 0)
+                       return len;
+               len = strnlen_user(name, retval);
+               if (len == 0 || len > __NEW_UTS_LEN)
+                       return -EINVAL;
+               memcpy_fromfs(system_utsname.nodename, name, len);
+               system_utsname.nodename[len] = '\0';
+               return 0;
+       case MIPS_ATOMIC_SET:
+               p = (int *) arg1;
+               retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
+               if(retval)
+                       return -EINVAL;
+               save_flags(flags);
+               cli();
+               retval = *p;
+               *p = arg2;
+               restore_flags(flags);
+               return retval;
+       case MIPS_FIXADE:
+               if (arg1)
+                       current->tss.mflags |= MF_FIXADE;
+               else
+                       current->tss.mflags |= MF_FIXADE;
+               retval = 0;
+               break;
+       case FLUSH_CACHE:
+               sys_cacheflush(0, ~0, BCACHE);
+               break;
+       }
+
+       return retval;
+}
+
+/*
+ * No implemented yet ...
+ */
+asmlinkage int
+sys_cachectl(char *addr, int nbytes, int op)
+{
+       return -ENOSYS;
+}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
new file mode 100644 (file)
index 0000000..ec2bb53
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ *  linux/arch/mips/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+#define TIMER_IRQ 0
+
+/* This function must be called with interrupts disabled 
+ * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
+ * 
+ * However, the pc-audio speaker driver changes the divisor so that
+ * it gets interrupted rather more often - it loads 64 into the
+ * counter rather than 11932! This has an adverse impact on
+ * do_gettimeoffset() -- it stops working! What is also not
+ * good is that the interval that our timer function gets called
+ * is no longer 10.0002 ms, but 9.9767 ms. To get around this
+ * would require using a different timing source. Maybe someone
+ * could use the RTC - I know that this can interrupt at frequencies
+ * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
+ * it so that at startup, the timer code in sched.c would select
+ * using either the RTC or the 8253 timer. The decision would be
+ * based on whether there was any other device around that needed
+ * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
+ * and then do some jiggery to have a version of do_timer that 
+ * advanced the clock by 1/1024 s. Every time that reached over 1/100
+ * of a second, then do all the old code. If the time was kept correct
+ * then do_gettimeoffset could just return 0 - there is no low order
+ * divider that can be accessed.
+ *
+ * Ideally, you would be able to use the RTC for the speaker driver,
+ * but it appears that the speaker driver really needs interrupt more
+ * often than every 120 us or so.
+ *
+ * Anyway, this needs more thought....         pjsg (1993-08-28)
+ * 
+ * If you are really that interested, you should be reading
+ * comp.protocols.time.ntp!
+ */
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+       int count;
+       unsigned long offset = 0;
+
+       /* timer count may underflow right here */
+       outb_p(0x00, 0x43);     /* latch the count ASAP */
+       count = inb_p(0x40);    /* read the latched count */
+       count |= inb(0x40) << 8;
+       /* we know probability of underflow is always MUCH less than 1% */
+       if (count > (LATCH - LATCH/100)) {
+               /* check for pending timer interrupt */
+               outb_p(0x0a, 0x20);
+               if (inb(0x20) & 1)
+                       offset = TICK_SIZE;
+       }
+       count = ((LATCH-1) - count) * TICK_SIZE;
+       count = (count + LATCH/2) / LATCH;
+       return offset + count;
+}
+
+static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+       *tv = xtime;
+       tv->tv_usec += do_gettimeoffset();
+       if (tv->tv_usec >= 1000000) {
+               tv->tv_usec -= 1000000;
+               tv->tv_sec++;
+       }
+       restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+       cli();
+       /* This is revolting. We need to set the xtime.tv_usec
+        * correctly. However, the value in this location is
+        * is value at the last tick.
+        * Discover what correction gettimeofday
+        * would have done, and then undo it!
+        */
+       tv->tv_usec -= do_gettimeoffset();
+
+       if (tv->tv_usec < 0) {
+               tv->tv_usec += 1000000;
+               tv->tv_sec--;
+       }
+
+       xtime = *tv;
+       time_state = TIME_BAD;
+       time_maxerror = 0x70000000;
+       time_esterror = 0x70000000;
+       sti();
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+       int retval = 0;
+       int real_seconds, real_minutes, cmos_minutes;
+       unsigned char save_control, save_freq_select;
+
+       save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+       CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+       save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+       cmos_minutes = CMOS_READ(RTC_MINUTES);
+       if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+               BCD_TO_BIN(cmos_minutes);
+
+       /*
+        * since we're only adjusting minutes and seconds,
+        * don't interfere with hour overflow. This avoids
+        * messing with unknown time zones but requires your
+        * RTC not to be off by more than 15 minutes
+        */
+       real_seconds = nowtime % 60;
+       real_minutes = nowtime / 60;
+       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+               real_minutes += 30;             /* correct for half hour time zone */
+       real_minutes %= 60;
+
+       if (abs(real_minutes - cmos_minutes) < 30) {
+               if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+                       BIN_TO_BCD(real_seconds);
+                       BIN_TO_BCD(real_minutes);
+               }
+               CMOS_WRITE(real_seconds,RTC_SECONDS);
+               CMOS_WRITE(real_minutes,RTC_MINUTES);
+       } else
+               retval = -1;
+
+       /* The following flags have to be released exactly in this order,
+        * otherwise the DS12887 (popular MC146818A clone with integrated
+        * battery and crystal) will not reset the oscillator and will not
+        * update precisely 500 ms later. You won't find this mentioned in
+        * the Dallas Semiconductor data sheets, but who believes data
+        * sheets anyway ...                           -- Markus Kuhn
+        */
+       CMOS_WRITE(save_control, RTC_CONTROL);
+       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+       return retval;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static void timer_interrupt(int irq, struct pt_regs * regs)
+{
+       do_timer(regs);
+
+       /*
+        * If we have an externally synchronized Linux clock, then update
+        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+        * called as close as possible to 500 ms before the new second starts.
+        */
+       if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+           xtime.tv_usec > 500000 - (tick >> 1) &&
+           xtime.tv_usec < 500000 + (tick >> 1))
+         if (set_rtc_mmss(xtime.tv_sec) == 0)
+           last_rtc_update = xtime.tv_sec;
+         else
+           last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+       /* As we return to user mode fire off the other CPU schedulers.. this is 
+          basically because we don't yet share IRQ's around. This message is
+          rigged to be safe on the 386 - basically its a hack, so don't look
+          closely for now.. */
+       smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+       unsigned int day, unsigned int hour,
+       unsigned int min, unsigned int sec)
+{
+       if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
+               mon += 12;      /* Puts Feb last since it has leap day */
+               year -= 1;
+       }
+       return (((
+           (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+             year*365 - 719499
+           )*24 + hour /* now have hours */
+          )*60 + min /* now have minutes */
+         )*60 + sec; /* finally seconds */
+}
+
+void time_init(void)
+{
+       void (*irq_handler)(int, struct pt_regs *);
+       unsigned int year, mon, day, hour, min, sec;
+       int i;
+
+       /* The Linux interpretation of the CMOS clock register contents:
+        * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+        * RTC registers show the second which has precisely just started.
+        * Let's hope other operating systems interpret the RTC the same way.
+        */
+       /* read RTC exactly on falling edge of update flag */
+       for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+               if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+                       break;
+       for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+               if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+                       break;
+       do { /* Isn't this overkill ? UIP above should guarantee consistency */
+               sec = CMOS_READ(RTC_SECONDS);
+               min = CMOS_READ(RTC_MINUTES);
+               hour = CMOS_READ(RTC_HOURS);
+               day = CMOS_READ(RTC_DAY_OF_MONTH);
+               mon = CMOS_READ(RTC_MONTH);
+               year = CMOS_READ(RTC_YEAR);
+       } while (sec != CMOS_READ(RTC_SECONDS));
+       if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+         {
+           BCD_TO_BIN(sec);
+           BCD_TO_BIN(min);
+           BCD_TO_BIN(hour);
+           BCD_TO_BIN(day);
+           BCD_TO_BIN(mon);
+           BCD_TO_BIN(year);
+         }
+       if ((year += 1900) < 1970)
+               year += 100;
+       xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+       xtime.tv_usec = 0;
+
+       /* FIXME: If we have the CPU hardware time counters, use them */
+       irq_handler = timer_interrupt;  
+
+       if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
+               panic("Could not allocate timer IRQ!");
+}
diff --git a/arch/mips/kernel/tlb.S b/arch/mips/kernel/tlb.S
deleted file mode 100644 (file)
index 6c86fa6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * arch/mips/kernel/head.S
- *
- * Copyright (C) 1994 Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * Head.S contains the MIPS exception handler and startup code.
- * Flush the TLB
- *
- * FIXME: knows only how to handle R4x00
- * Read appendix f of the R4000 manual before you change something!
- */
-
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/bootinfo.h>
-
-               .globl  _tlbflush
-_tlbflush:     li      t0,PM_4K
-               mtc0    t0,CP0_PAGEMASK
-               lw      t0,_boot_info+OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-       li      t0,48
-               dmtc0   zero,CP0_ENTRYLO0
-               dmtc0   zero,CP0_ENTRYLO1
-               mfc0    t2,CP0_WIRED
-1:             subu    t0,t0,1
-               mtc0    t0,CP0_INDEX
-               lui     t1,0x0008
-               or      t1,t0,t1
-               dsll    t1,t1,13
-               dmtc0   t1,CP0_ENTRYHI
-               bne     t2,t0,1b
-               tlbwi                                   # delay slot
-               jr      ra
-               nop
index c38d824599ebc556fd3420e6b5fd7daf6956684f..46ecaa69ac552fe9f7b57a1209e92f378bf3a00c 100644 (file)
@@ -1,7 +1,9 @@
 /*
  *  arch/mips/kernel/traps.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 
 /*
  * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
  * to mainly kill the offending process (probably by giving it a signal,
  * but possibly by killing it outright if necessary).
+ *
+ * FIXME: This is the place for a fpu emulator.
  */
 #include <linux/head.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/string.h>
+#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/config.h>
 #include <linux/timer.h>
+#include <linux/mm.h>
 
+#include <asm/vector.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -32,18 +40,15 @@ static inline void console_verbose(void)
        console_loglevel = 15;
 }
 
-#define get_seg_byte(seg,addr) ({ \
-register unsigned char __res; \
-__res = get_user_byte(addr); \
-__res;})
-
-#define get_seg_long(seg,addr) ({ \
-register unsigned long __res; \
-__res = get_user_word(addr); \
-__res;})
-
-extern asmlinkage void deskstation_tyne_handle_int(void);
+/*
+ * Machine specific interrupt handlers
+ */
 extern asmlinkage void acer_pica_61_handle_int(void);
+extern asmlinkage void decstation_handle_int(void);
+extern asmlinkage void deskstation_rpc44_handle_int(void);
+extern asmlinkage void deskstation_tyne_handle_int(void);
+extern asmlinkage void mips_magnum_4000_handle_int(void);
+
 extern asmlinkage void handle_mod(void);
 extern asmlinkage void handle_tlbl(void);
 extern asmlinkage void handle_tlbs(void);
@@ -63,90 +68,60 @@ extern asmlinkage void handle_vced(void);
 extern asmlinkage void handle_watch(void);
 extern asmlinkage void handle_reserved(void);
 
-char *cpu_names[] = CPU_NAMES;
+static char *cpu_names[] = CPU_NAMES;
+
+unsigned long page_colour_mask;
 
 int kstack_depth_to_print = 24;
 
 /*
- * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
+ * These constant is for searching for possible module text segments.
+ * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
  */
-#define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
-       int i;
-       unsigned long *sp, *pc;
-       unsigned long *stack, addr, module_start, module_end;
-       extern char start_kernel, etext;
+       int     i;
+       int     *stack;
+       u32     *sp, *pc, addr, module_start, module_end;
+       extern  char start_kernel, _etext;
 
        if ((regs->cp0_status & (ST0_ERL|ST0_EXL)) == 0)
                return;
 
-       sp = (unsigned long *)regs->reg29;
-       pc = (unsigned long *)regs->cp0_epc;
+       sp = (u32 *)regs->reg29;
+       pc = (u32 *)regs->cp0_epc;
 
        console_verbose();
        printk("%s: %08lx\n", str, err );
 
-       /*
-        * Saved main processor registers
-        */
-       printk("at   : %08lx\n", regs->reg1);
-       printk("v0   : %08lx %08lx\n", regs->reg2, regs->reg3);
-       printk("a0   : %08lx %08lx %08lx %08lx\n",
-              regs->reg4, regs->reg5, regs->reg6, regs->reg7);
-       printk("t0   : %08lx %08lx %08lx %08lx %08lx\n",
-              regs->reg8, regs->reg9, regs->reg10, regs->reg11, regs->reg12);
-       printk("t5   : %08lx %08lx %08lx %08lx %08lx\n",
-              regs->reg13, regs->reg14, regs->reg15, regs->reg24, regs->reg25);
-       printk("s0   : %08lx %08lx %08lx %08lx\n",
-              regs->reg16, regs->reg17, regs->reg18, regs->reg19);
-       printk("s4   : %08lx %08lx %08lx %08lx\n",
-              regs->reg20, regs->reg21, regs->reg22, regs->reg23);
-       printk("gp   : %08lx\n", regs->reg28);
-       printk("sp   : %08lx\n", regs->reg29);
-       printk("fp/s8: %08lx\n", regs->reg30);
-       printk("ra   : %08lx\n", regs->reg31);
-
-       /*
-        * Saved cp0 registers
-        */
-       printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
-              regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
-
-       /*
-        * Some goodies...
-        */
-       printk("Int  : %ld\n", regs->interrupt);
+       show_regs(regs);
 
        /*
         * Dump the stack
         */
-       if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
+       if (STACK_MAGIC != *(u32 *)current->kernel_stack_page)
                printk("Corrupted stack page\n");
-       printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
-               current->comm, current->pid, 0xffff & i,
-               current->kernel_stack_page);
+       printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
+               current->comm, current->pid, current->kernel_stack_page);
        for(i=0;i<5;i++)
-               printk("%08lx ", *sp++);
-       stack = (unsigned long *) sp;
+               printk("%08x ", *sp++);
+       stack = (int *) sp;
        for(i=0; i < kstack_depth_to_print; i++) {
-               if (((long) stack & 4095) == 0)
+               if (((u32) stack & (PAGE_SIZE -1)) == 0)
                        break;
                if (i && ((i % 8) == 0))
                        printk("\n       ");
-               printk("%08lx ", get_seg_long(ss,stack++));
+               printk("%08lx ", get_user(stack++));
        }
        printk("\nCall Trace: ");
-       stack = (unsigned long *) sp;
+       stack = (int *)sp;
        i = 1;
-       module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+       module_start = VMALLOC_START;
        module_end = module_start + MODULE_RANGE;
-       while (((long) stack & 4095) != 0) {
-               addr = get_seg_long(ss, stack++);
+       while (((u32)stack & (PAGE_SIZE -1)) != 0) {
+               addr = get_user(stack++);
                /*
                 * If the address is either in the text segment of the
                 * kernel, or in the region which contains vmalloc'ed
@@ -155,103 +130,159 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
                 * down the cause of the crash will be able to figure
                 * out the call path that was taken.
                 */
-               if (((addr >= (unsigned long) &start_kernel) &&
-                    (addr <= (unsigned long) &etext)) ||
+               if (((addr >= (u32) &start_kernel) &&
+                    (addr <= (u32) &_etext)) ||
                    ((addr >= module_start) && (addr <= module_end))) {
                        if (i && ((i % 8) == 0))
                                printk("\n       ");
-                       printk("%08lx ", addr);
+                       printk("%08x ", addr);
                        i++;
                }
        }
 
        printk("\nCode : ");
-       for(i=0;i<5;i++)
-               printk("%08lx ", *pc++);
-       printk("\n");
+       if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
+            KSEGX(pc) == KSEG0 ||
+            KSEGX(pc) == KSEG1) &&
+           (((unsigned long) pc & 3) == 0))
+       {
+               for(i=0;i<5;i++)
+                       printk("%08x ", *pc++);
+               printk("\n");
+       }
+       else
+               printk("(Bad address in epc)\n");
+while(1);
        do_exit(SIGSEGV);
 }
 
+static void
+fix_ade(struct pt_regs *regs, int write)
+{
+       printk("Received address error (ade%c)\n", write ? 's' : 'l');
+       panic("Fixing address errors not implemented yet");
+}
+
 void do_adel(struct pt_regs *regs)
 {
+       if(current->tss.mflags & MF_FIXADE)
+       {
+               fix_ade(regs, 0);
+               return;
+       }
+       show_regs(regs);
+while(1);
+       dump_tlb_nonwired();
        send_sig(SIGSEGV, current, 1);
 }
 
 void do_ades(struct pt_regs *regs)
 {
+       unsigned long   pc = regs->cp0_epc;
+       int     i;
+
+       if(current->tss.mflags & MF_FIXADE)
+       {
+               fix_ade(regs, 1);
+               return;
+       }
+while(1);
+       for(i=0; i<NR_TASKS;i++)
+               if(task[i] && task[i]->pid >= 2)
+               {
+                       printk("Process %d\n", task[i]->pid);
+                       dump_list_process(task[i], pc);
+               }
+       show_regs(regs);
+       dump_tlb_nonwired();
        send_sig(SIGSEGV, current, 1);
 }
 
+/*
+ * The ibe/dbe exceptions are signaled by onboard hardware and should get
+ * a board specific handlers to get maximum available information. Bus
+ * errors are always symptom of hardware malfunction or a kernel error.
+ *
+ * FIXME: Linux/68k sends a SIGSEGV for a buserror which seems to be wrong.
+ * This is certainly wrong. Actually, all hardware errors (ades,adel,ibe,dbe)
+ * are bus errors and therefor should send a SIGBUS! (Andy)
+ */
 void do_ibe(struct pt_regs *regs)
 {
-       send_sig(SIGSEGV, current, 1);
+show_regs(regs);
+while(1);
+       send_sig(SIGBUS, current, 1);
 }
 
 void do_dbe(struct pt_regs *regs)
 {
-       send_sig(SIGSEGV, current, 1);
+show_regs(regs);
+while(1);
+       send_sig(SIGBUS, current, 1);
 }
 
 void do_ov(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
        send_sig(SIGFPE, current, 1);
 }
 
 void do_fpe(struct pt_regs *regs)
 {
-       /*
-        * FIXME: This is the place for a fpu emulator. Not written
-        * yet and the demand seems to be quite low.
-        */
-       printk("Caught FPE exception at %lx.\n", regs->cp0_epc);
+show_regs(regs);
+while(1);
        send_sig(SIGFPE, current, 1);
 }
 
 void do_bp(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
        send_sig(SIGILL, current, 1);
 }
 
 void do_tr(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
        send_sig(SIGILL, current, 1);
 }
 
 void do_ri(struct pt_regs *regs)
 {
+       int     i;
+
+       for(i=0; i<NR_TASKS;i++)
+               if(task[i] && task[i]->pid >= 2)
+               {
+                       printk("Process %d\n", task[i]->pid);
+                       dump_list_process(task[i], 0x7ffff000);
+               }
+       show_regs(regs);
+while(1);
        send_sig(SIGILL, current, 1);
 }
 
 void do_cpu(struct pt_regs *regs)
 {
-       unsigned long pc;
-       unsigned int insn;
+       unsigned int cpid;
 
-       /*
-        * Check whether this was a cp1 instruction
-        */
-       pc = regs->cp0_epc;
-       if (regs->cp0_cause & (1<<31))
-               pc += 4;
-       insn = *(unsigned int *)pc;
-       insn &= 0xfc000000;
-       switch(insn) {
-               case 0x44000000:
-               case 0xc4000000:
-               case 0xe4000000:
-                       printk("CP1 instruction - enabling cp1.\n");
-                       regs->cp0_status |= ST0_CU1;
-                       /*
-                        * No need to handle branch delay slots
-                        */
-                       break;
-               default:
-                       /*
-                        * This wasn't a cp1 instruction and therefore illegal.
-                        * Default is to kill the process.
-                        */
-                       send_sig(SIGILL, current, 1);
-               }
+       cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
+       switch(cpid)
+       {
+       case 1:
+               regs->cp0_status |= ST0_CU1;
+               break;
+       case 0:
+               /*
+                * CPU for cp0 can only happen in user mode
+                */
+       case 2:
+       case 3:
+               send_sig(SIGILL, current, 1);
+               break;
+       }
 }
 
 void do_vcei(struct pt_regs *regs)
@@ -274,10 +305,6 @@ void do_vced(struct pt_regs *regs)
 
 void do_watch(struct pt_regs *regs)
 {
-       /*
-        * Only possible on R4[04]00. No way to handle this because
-        * I don't have such a cpu.
-        */
        panic("Caught WATCH exception - can't handle yet\n");
 }
 
@@ -285,7 +312,7 @@ void do_reserved(struct pt_regs *regs)
 {
        /*
         * Game over - no way to handle this if it ever occurs.
-        * Most probably caused by a new unknown cpu type or a
+        * Most probably caused by a new unknown cpu type or
         * after another deadly hard/software error.
         */
        panic("Caught reserved exception - can't handle.\n");
@@ -293,12 +320,11 @@ void do_reserved(struct pt_regs *regs)
 
 void trap_init(void)
 {
-       int     i;
+       unsigned long   i;
+       void watch_set(unsigned long, unsigned long);
 
-       /*
-        * FIXME: Mips Magnum R4000 has an EISA bus!
-        */
-       EISA_bus = 0;
+       if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
+               EISA_bus = 1;
 
        /*
         * Setup default vectors
@@ -310,30 +336,49 @@ void trap_init(void)
         * Handling the following exceptions depends mostly of the cpu type
         */
        switch(boot_info.cputype) {
+       /*
+        * The R10000 is in most aspects similar to the R4400.  It however
+        * should get some special optimizations.
+        */
+       case CPU_R10000:
+               write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+               set_cp0_status(ST0_XX, ST0_XX);
+               page_colour_mask = 0x3000;
+               panic("CPU too expensive - making holiday in the ANDES!");
+               break;
        case CPU_R4000MC:
        case CPU_R4400MC:
        case CPU_R4000SC:
        case CPU_R4400SC:
                /*
-                * Handlers not implemented yet
+                * Handlers not implemented yet.  If should ever be used -
+                * otherwise it's a bug in the Linux/MIPS kernel, anyway.
                 */
                set_except_vector(14, handle_vcei);
                set_except_vector(31, handle_vced);
        case CPU_R4000PC:
        case CPU_R4400PC:
+       case CPU_R4200:
+     /* case CPU_R4300: */
                /*
-                * Handler not implemented yet
+                * Use watch exception to trap on access to address zero
                 */
                set_except_vector(23, handle_watch);
-       case CPU_R4200:
+               watch_set(KSEG0, 3);
        case CPU_R4600:
                set_except_vector(1, handle_mod);
                set_except_vector(2, handle_tlbl);
                set_except_vector(3, handle_tlbs);
                set_except_vector(4, handle_adel);
                set_except_vector(5, handle_ades);
+               /*
+                * The following two are signaled by onboard hardware and
+                * should get board specific handlers to get maximum
+                * available information.
+                */
                set_except_vector(6, handle_ibe);
                set_except_vector(7, handle_dbe);
+
                set_except_vector(8, handle_sys);
                set_except_vector(9, handle_bp);
                set_except_vector(10, handle_ri);
@@ -341,6 +386,15 @@ void trap_init(void)
                set_except_vector(12, handle_ov);
                set_except_vector(13, handle_tr);
                set_except_vector(15, handle_fpe);
+
+               /*
+                * Compute mask for page_colour().  This is based on the
+                * size of the data cache.  Does the size of the icache
+                * need to be accounted for?
+                */
+               i = read_32bit_cp0_register(CP0_CONFIG);
+               i = (i >> 26) & 7;
+               page_colour_mask = 1 << (12 + i);
                break;
        case CPU_R2000:
        case CPU_R3000:
@@ -353,27 +407,18 @@ void trap_init(void)
        case CPU_R6000:
        case CPU_R6000A:
        case CPU_R8000:
-       case CPU_R10000:
                printk("Detected unsupported CPU type %s.\n",
-                      cpu_names[boot_info.cputype]);
+                       cpu_names[boot_info.cputype]);
                panic("Can't handle CPU\n");
                break;
+
        case CPU_UNKNOWN:
        default:
-               panic("Unknown type of CPU");
-               }
+               panic("Unknown CPU type");
+       }
 
        /*
-        * The interrupt handler depends of both type of the board and cpu
+        * The interrupt handler mostly depends of the board type.
         */
-       switch(boot_info.machtype) {
-       case MACH_DESKSTATION_TYNE:
-               set_except_vector(0, deskstation_tyne_handle_int);
-               break;
-       case MACH_ACER_PICA_61:
-               set_except_vector(0, acer_pica_61_handle_int);
-               break;
-       default:
-               panic("Unknown machine type");
-               }
+       set_except_vector(0, feature->handle_int);
 }
diff --git a/arch/mips/kernel/tyne-c.c b/arch/mips/kernel/tyne-c.c
new file mode 100644 (file)
index 0000000..71e3068
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Deskstation Tyne specific C parts
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+/*
+ * How to access the FDC's registers.
+ */
+unsigned char deskstation_tyne_fd_inb(unsigned int port)
+{
+       return inb_p(port);
+}
+
+void deskstation_tyne_fd_outb(unsigned char value, unsigned int port)
+{
+       outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+void deskstation_tyne_fd_enable_dma(void)
+{
+       enable_dma(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_disable_dma(void)
+{
+       disable_dma(FLOPPY_DMA);
+}
+
+int deskstation_tyne_fd_request_dma(void)
+{
+       return request_dma(FLOPPY_DMA, "floppy");
+}
+
+void deskstation_tyne_fd_free_dma(void)
+{
+       free_dma(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_clear_dma_ff(void)
+{
+       clear_dma_ff(FLOPPY_DMA);
+}
+
+int deskstation_tyne_fd_set_dma_mode(char mode)
+{
+       return set_dma_mode(FLOPPY_DMA, mode);
+}
+
+void deskstation_tyne_fd_set_dma_addr(unsigned int a)
+{
+       set_dma_addr(FLOPPY_DMA, addr);
+}
+
+void deskstation_tyne_fd_set_dma_count(unsigned int count)
+{
+       set_dma_count(FLOPPY_DMA, count);
+}
+
+int deskstation_tyne_fd_get_dma_residue(void)
+{
+       return get_dma_residue(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_enable_irq(void)
+{
+       enable_irq(FLOPPY_IRQ);
+}
+
+void deskstation_tyne_fd_disable_irq(void)
+{
+       disable_irq(FLOPPY_IRQ);
+}
+
+void deskstation_tyne_fd_cacheflush(unsigned char *addr, unsigned int)
+{
+       sys_cacheflush((void *)addr, size, DCACHE);
+}
+
+
+/*
+ * Tiny Tyne DMA buffer allocator
+ *
+ * Untested for a long time and changed again and again ...
+ * Sorry, but no hardware to test ...
+ */
+static unsigned long allocated;
+
+/*
+ * Not very sophisticated, but should suffice for now...
+ */
+unsigned long deskstation_tyne_dma_alloc(size_t size)
+{
+       unsigned long ret = allocated;
+       allocated += size;
+       if (allocated > boot_info.dma_cache_size)
+               ret = -1;
+       return ret;
+}
+
+void deskstation_tyne_dma_init(void)
+{
+       if (boot_info.machtype != MACH_DESKSTATION_TYNE)
+               return;
+       allocated = 0;
+       printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
+               boot_info.dma_cache_size >> 10);
+}
diff --git a/arch/mips/kernel/tyne.S b/arch/mips/kernel/tyne.S
new file mode 100644 (file)
index 0000000..8c80afc
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * arch/mips/kernel/tyne.S
+ *
+ * Deskstation Tyne specific Assembler code
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+/*
+ * Deskstation Tyne interrupt handler
+ */
+               .text
+               .set    noreorder
+               .set    noat
+               .align  5
+               NESTED(deskstation_tyne_handle_int, FR_SIZE, sp)
+               SAVE_ALL
+               CLI
+               .set    at
+               lui     s0,%hi(PORT_BASE)
+               li      t1,0x0f
+               sb      t1,%lo(PORT_BASE+0x20)(s0)      # poll command
+               lb      t1,%lo(PORT_BASE+0x20)(s0)      # read result
+               li      s1,1
+               bgtz    t1,Lpoll_second
+               andi    t1,t1,7
+               /*
+                * Acknowledge first pic
+                */
+               lb      t2,%lo(PORT_BASE+0x21)(s0)
+               lui     s4,%hi(cache_21)
+               lb      t0,%lo(cache_21)(s4)
+               sllv    s1,s1,t1
+               or      t0,t0,s1
+               sb      t0,%lo(cache_21)(s4)
+               sb      t0,%lo(PORT_BASE+0x21)(s0)
+               lui     s3,%hi(intr_count)
+               lw      t0,%lo(intr_count)(s3)
+               li      t2,0x20
+               sb      t2,%lo(PORT_BASE+0x20)(s0)
+               /*
+                * Now call the real handler
+                */
+               la      t3,IRQ_vectors
+               sll     t2,t1,2
+               addu    t3,t3,t2
+               lw      t3,(t3)
+               addiu   t0,t0,1
+               jalr    t3
+               sw      t0,%lo(intr_count)(s3)                  # delay slot
+               lw      t0,%lo(intr_count)(s3)
+               /*
+                * Unblock first pic
+                */
+               lbu     t1,%lo(PORT_BASE+0x21)(s0)
+               lb      t1,%lo(cache_21)(s4)
+               subu    t0,t0,1
+               sw      t0,%lo(intr_count)(s3)
+               nor     s1,zero,s1
+               and     t1,t1,s1
+               sb      t1,%lo(cache_21)(s4)
+               jr      v0
+               sb      t1,%lo(PORT_BASE+0x21)(s0)      # delay slot
+
+               .align  5
+Lpoll_second:  li      t1,0x0f
+               sb      t1,%lo(PORT_BASE+0xa0)(s0)      # poll command
+               lb      t1,%lo(PORT_BASE+0xa0)(s0)      # read result
+               lui     s4,%hi(cache_A1)
+               bgtz    t1,spurious_interrupt
+               andi    t1,t1,7
+               /*
+                * Acknowledge second pic
+                */
+               lbu     t2,%lo(PORT_BASE+0xa1)(s0)
+               lb      t3,%lo(cache_A1)(s4)
+               sllv    s1,s1,t1
+               or      t3,t3,s1
+               sb      t3,%lo(cache_A1)(s4)
+               sb      t3,%lo(PORT_BASE+0xa1)(s0)
+               li      t3,0x20
+               sb      t3,%lo(PORT_BASE+0xa0)(s0)
+               lui     s3,%hi(intr_count)
+               lw      t0,%lo(intr_count)(s3)
+               sb      t3,%lo(PORT_BASE+0x20)(s0)
+               /*
+                * Now call the real handler
+                */
+               la      t0,IRQ_vectors
+               sll     t2,t1,2
+               addu    t0,t0,t2
+               lw      t0,32(t0)
+               addiu   t0,t0,1
+               jalr    t0
+               sw      t0,%lo(intr_count)(s3)                  # delay slot
+               lw      t0,%lo(intr_count)(s3)
+               /*
+                * Unblock second pic
+                */
+               lb      t1,%lo(PORT_BASE+0xa1)(s0)
+               lb      t1,%lo(cache_A1)(s4)
+               subu    t0,t0,1
+               lw      t0,%lo(intr_count)(s3)
+               nor     s1,zero,s1
+               and     t1,t1,s1
+               sb      t1,%lo(cache_A1)(s4)
+               jr      v0
+               sb      t1,%lo(PORT_BASE+0xa1)(s0)      # delay slot
+               END(deskstation_tyne_handle_int)
+
+               .align  5
+LEAF(spurious_interrupt)
+               /*
+                * Nothing happened... (whistle)
+                */
+               lui     t1,%hi(spurious_count)
+               lw      t0,%lo(spurious_count)(t1)
+               la      v0,return
+               addiu   t0,1
+               jr      ra
+               sw      t0,%lo(spurious_count)(t1)
+               END(spurious_interrupt)
+
diff --git a/arch/mips/kernel/tynedma.c b/arch/mips/kernel/tynedma.c
deleted file mode 100644 (file)
index 28ba6bf..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Tiny Tyne DMA buffer allocator
- *
- * Copyright (C) 1995 Ralf Baechle
- */
-#include <linux/autoconf.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_DESKSTATION_TYNE
-
-static unsigned long allocated;
-
-/*
- * Not very sophisticated, but should suffice for now...
- */
-unsigned long deskstation_tyne_dma_alloc(size_t size)
-{
-       unsigned long ret = allocated;
-       allocated += size;
-       if (allocated > boot_info.dma_cache_size)
-               ret = -1;
-       return ret;
-}
-
-void deskstation_tyne_dma_init(void)
-{
-       if (boot_info.machtype != MACH_DESKSTATION_TYNE)
-               return;
-       allocated = 0;
-       printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
-               boot_info.dma_cache_size >> 10);
-}
-
-#endif /* CONFIG_DESKSTATION_TYNE */
diff --git a/arch/mips/ld.script b/arch/mips/ld.script
new file mode 100644 (file)
index 0000000..26464d9
--- /dev/null
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)      }
+  .rela.text     : { *(.rela.text)     }
+  .rel.data      : { *(.rel.data)      }
+  .rela.data     : { *(.rela.data)     }
+  .rel.rodata    : { *(.rel.rodata)    }
+  .rela.rodata   : { *(.rela.rodata)   }
+  .rel.got       : { *(.rel.got)       }
+  .rela.got      : { *(.rela.got)      }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.init      : { *(.rel.init)      }
+  .rela.init     : { *(.rela.init)     }
+  .rel.fini      : { *(.rel.fini)      }
+  .rela.fini     : { *(.rela.fini)     }
+  .rel.bss       : { *(.rel.bss)       }
+  .rela.bss      : { *(.rela.bss)      }
+  .rel.plt       : { *(.rel.plt)       }
+  .rela.plt      : { *(.rela.plt)      }
+  .init          : { *(.init)          } =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
new file mode 100644 (file)
index 0000000..5fb44a4
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Makefile for MIPS-specific library files..
+#
+# Many of these routines are just left over debugging trash of ancient
+# times when I just make my Tyne beep and so ...
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+L_TARGET = lib.a
+L_OBJS = beep.o checksum.o csum.o dump_tlb.o tinycon.o watch.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/lib/checksum.c b/arch/mips/lib/checksum.c
new file mode 100644 (file)
index 0000000..1b78f3c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors:    Ralf Baechle, <ralf@waldorf-gmbh.de>
+ *             Lots of code moved from tcp.c and ip.c; see those files
+ *             for more names.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+#include <net/checksum.h>
+#include <asm/string.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+       unsigned long   scratch1;
+       unsigned long   scratch2;
+
+       /*
+        * The GCC generated code for handling carry bits makes
+        * it strongly desireable to do this in assembler!
+        */
+    __asm__("
+       .set    noreorder
+       .set    noat
+       andi    $1,%5,2         # Check alignment
+       beqz    $1,2f           # Branch if ok
+       subu    $1,%4,2         # delay slot, Alignment uses up two bytes
+       bgez    $1,1f           # Jump if we had at least two bytes
+       move    %4,$1           # delay slot
+       j       4f
+       addiu   %4,2            # delay slot; len was < 2.  Deal with it
+
+1:     lw      %2,(%5)
+       addiu   %4,2
+       addu    %0,%2
+       sltu    $1,%0,%2
+       addu    %0,$1
+
+2:     move    %1,%4
+       srl     %1,%1,5
+       beqz    %1,2f
+       sll     %1,%1,5         # delay slot
+
+       addu    %1,%5
+1:     lw      %2,0(%5)
+       addu    %5,32
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-28(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-24(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-20(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-16(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-12(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-8(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       lw      %2,-4(%5)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+
+       bne     %5,%1,1b
+       addu    %0,$1           # delay slot
+
+2:     andi    %1,%4,0x1c
+       srl     %1,%1,2
+       beqz    %1,4f
+       addu    %1,%5           # delay slot
+3:     lw      %2,0(%5)
+       addu    %5,4
+       addu    %0,%2
+       sltu    $1,%0,%2
+       bne     %5,%1,3b
+       addu    %0,$1           # delay slot
+
+4:     andi    $1,%3,2
+       beqz    $1,5f
+       move    %2,$0           # delay slot
+       lhu     %2,(%5)
+       addiu   %5,2
+
+5:     andi    $1,%3,1
+       beqz    $1,6f
+       sll     %1,16           # delay slot
+       lbu     %1,(%5)
+       nop                     # NOP ALERT (spit, gasp)
+6:     or      %2,%1
+       addu    %0,%2
+       sltu    $1,%0,%2
+       addu    %0,$1
+7:     .set    at
+       .set    reorder"
+       : "=r"(sum), "=r" (scratch1), "=r" (scratch2)
+       : "0"(sum), "r"(len), "r"(buff)
+       : "$1");
+
+       return sum;
+}
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, 
+                                 int len, int sum)
+{
+       /*
+        * It's 2:30 am and I don't feel like doing it real ...
+        * This is lots slower than the real thing (tm)
+        */
+       sum = csum_partial(src, len, sum);
+       memcpy(dst, src, len);
+
+       return sum;
+}
index d327551d013a0bba7ba4b3af7349e89513e1d6d8..d7049a660cc665f9ba2c52d1aae0ffa5edbe9063 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for the linux mips-specific parts of the memory manager.
+# Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
index cd8b116773f6d5e65dd83a55c1bbdb39ef49d140..9dc43e76f4ff0a5b6e5e4f3cbe26e7c6eafc0fbd 100644 (file)
@@ -1,11 +1,8 @@
 /*
  *  arch/mips/mm/fault.c
  *
- *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
- *  Ported to MIPS by Ralf Baechle
+ *  Copyright (C) 1995 by Ralf Baechle
  */
-
-#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/head.h>
@@ -19,7 +16,7 @@
 
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <asm/mipsconfig.h>
+#include <asm/pgtable.h>
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 
@@ -27,61 +24,43 @@ extern void die_if_kernel(char *, struct pt_regs *, long);
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
- *
- * The error_code parameter just the same as in the i386 version:
- *
- *     bit 0 == 0 means no page found, 1 means protection fault
- *     bit 1 == 0 means read, 1 means write
- *     bit 2 == 0 means kernel, 1 means user-mode
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+asmlinkage void
+do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address)
 {
        struct vm_area_struct * vma;
-       unsigned long address;
-       unsigned long page;
 
-       /* get the address */
-       __asm__("dmfc0\t%0,$8"
-               : "=r" (address));
-
-       for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
-               if (!vma)
-                       goto bad_area;
-               if (vma->vm_end > address)
-                       break;
-       }
+#if 0
+       printk("do_page_fault() #1: %s %08lx (epc == %08lx, ra == %08lx)\n",
+              writeaccess ? "writeaccess to" : "readaccess from",
+              address, regs->cp0_epc, regs->reg31);
+#endif
+       vma = find_vma(current, address);
+       if (!vma)
+               goto bad_area;
        if (vma->vm_start <= address)
                goto good_area;
        if (!(vma->vm_flags & VM_GROWSDOWN))
                goto bad_area;
-       if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
+       if (expand_stack(vma, address))
                goto bad_area;
-       vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
-       vma->vm_start = (address & PAGE_MASK);
 /*
  * Ok, we have a good vm_area for this memory access, so
  * we can handle it..
  */
 good_area:
-       /*
-        * was it a write?
-        */
-       if (error_code & 2) {
+       if (writeaccess) {
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               /* read with protection fault? */
-               if (error_code & 1)
-                       goto bad_area;
                if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
                        goto bad_area;
        }
-       if (error_code & 1) {
-               do_wp_page(vma, address, error_code & 2);
-               return;
-       }
-       do_no_page(vma, address, error_code & 2);
-       return;
+       handle_mm_fault(vma, address, writeaccess);
+       /* FIXME: This flushes the cache far to often */
+       sys_cacheflush(address, PAGE_SIZE, BCACHE);
+
+        return;
 
 /*
  * Something tried to access memory that isn't in our memory map..
@@ -90,10 +69,7 @@ good_area:
 bad_area:
        if (user_mode(regs)) {
                current->tss.cp0_badvaddr = address;
-               current->tss.error_code = error_code;
-#if 0
-               current->tss.trap_no = 14;
-#endif
+               current->tss.error_code = writeaccess;
                send_sig(SIGSEGV, current, 1);
                return;
        }
@@ -101,22 +77,8 @@ bad_area:
         * Oops. The kernel tried to access some bad page. We'll have to
         * terminate things with extreme prejudice.
         */
-       if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
-               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-               pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
-       } else
-               printk(KERN_ALERT "Unable to handle kernel paging request");
-       printk(" at virtual address %08lx\n",address);
-       page = current->tss.pg_dir;
-       printk(KERN_ALERT "current->tss.pg_dir = %08lx\n", page);
-       page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
-       printk(KERN_ALERT "*pde = %08lx\n", page);
-       if (page & 1) {
-               page &= PAGE_MASK;
-               address &= 0x003ff000;
-               page = ((unsigned long *) page)[address >> PAGE_SHIFT];
-               printk(KERN_ALERT "*pte = %08lx\n", page);
-       }
-       die_if_kernel("Oops", regs, error_code);
+       printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
+              "address %08lx\n", address);
+       die_if_kernel("Oops", regs, writeaccess);
        do_exit(SIGKILL);
 }
index 5aed0fa692c8646c9a2a3dfd5b0c0e700a4a7b19..24bd07a2b4d3bef7b7bb241ff51448e30fb5ca6f 100644 (file)
@@ -4,7 +4,6 @@
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *  Ported to MIPS by Ralf Baechle
  */
-
 #include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 
+#include <asm/cachectl.h>
+#include <asm/jazzdma.h>
+#include <asm/vector.h>
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <asm/mipsconfig.h>
-
-extern unsigned long pg0[1024];                /* page table for 0-4MB for everybody */
+#include <asm/pgtable.h>
 
 extern void deskstation_tyne_dma_init(void);
 extern void scsi_mem_init(unsigned long);
@@ -29,6 +29,8 @@ extern void sound_mem_init(void);
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
+extern char empty_zero_page[PAGE_SIZE];
+
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -45,86 +47,177 @@ extern void show_net_buffers(void);
 pte_t * __bad_pagetable(void)
 {
        extern char empty_bad_page_table[PAGE_SIZE];
-       unsigned long dummy;
+       unsigned long page;
+       unsigned long dummy1, dummy2;
 
+       page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
+#if __mips__ >= 3
+        /*
+         * Use 64bit code even for Linux/MIPS 32bit on R4000
+         */
        __asm__ __volatile__(
-               ".set\tnoreorder\n\t"
+               ".set\tnoreorder\n"
+               ".set\tnoat\n\t"
+               ".set\tmips3\n\t"
+               "dsll32\t$1,%2,0\n\t"
+               "dsrl32\t%2,$1,0\n\t"
+               "or\t%2,$1\n"
+               "1:\tsd\t%2,(%0)\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,8\n\t"
+               ".set\tmips0\n\t"
+               ".set\tat\n"
+               ".set\treorder"
+               :"=r" (dummy1),
+                "=r" (dummy2)
+               :"r" (pte_val(BAD_PAGE)),
+                "0" (page),
+                "1" (PAGE_SIZE/8));
+#else
+       __asm__ __volatile__(
+               ".set\tnoreorder\n"
                "1:\tsw\t%2,(%0)\n\t"
-               "subu\t%1,%1,1\n\t"
-               "bne\t$0,%1,1b\n\t"
-               "addiu\t%0,%0,1\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,4\n\t"
                ".set\treorder"
-               :"=r" (dummy),
-                "=r" (dummy)
+               :"=r" (dummy1),
+                "=r" (dummy2)
                :"r" (pte_val(BAD_PAGE)),
-                "0" ((long) empty_bad_page_table),
-                "1" (PTRS_PER_PAGE));
+                "0" (page),
+                "1" (PAGE_SIZE/4));
+#endif
 
-       return (pte_t *) empty_bad_page_table;
+       return (pte_t *)page;
 }
 
-pte_t __bad_page(void)
+static inline void
+__zeropage(unsigned long page)
 {
-       extern char empty_bad_page[PAGE_SIZE];
-       unsigned long dummy;
+       unsigned long dummy1, dummy2;
 
+#ifdef __R4000__
+        /*
+         * Use 64bit code even for Linux/MIPS 32bit on R4000
+         */
+       __asm__ __volatile__(
+               ".set\tnoreorder\n"
+               ".set\tnoat\n\t"
+               ".set\tmips3\n"
+               "1:\tsd\t$0,(%0)\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,8\n\t"
+               ".set\tmips0\n\t"
+               ".set\tat\n"
+               ".set\treorder"
+               :"=r" (dummy1),
+                "=r" (dummy2)
+               :"0" (page),
+                "1" (PAGE_SIZE/8));
+#else
        __asm__ __volatile__(
-               ".set\tnoreorder\n\t"
+               ".set\tnoreorder\n"
                "1:\tsw\t$0,(%0)\n\t"
-               "subu\t%1,%1,1\n\t"
-               "bne\t$0,%1,1b\n\t"
-               "addiu\t%0,%0,1\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,4\n\t"
                ".set\treorder"
-               :"=r" (dummy),
-                "=r" (dummy)
-               :"0" ((long) empty_bad_page),
-                "1" (PTRS_PER_PAGE));
+               :"=r" (dummy1),
+                "=r" (dummy2)
+               :"0" (page),
+                "1" (PAGE_SIZE/4));
+#endif
+}
 
-       return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
+static inline void
+zeropage(unsigned long page)
+{
+       sys_cacheflush((void *)page, PAGE_SIZE, BCACHE);
+       sync_mem();
+       __zeropage(page + (PT_OFFSET - PAGE_OFFSET));
+}
+
+pte_t __bad_page(void)
+{
+       extern char empty_bad_page[PAGE_SIZE];
+       unsigned long page = (unsigned long)empty_bad_page;
+
+       zeropage(page);
+       return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 }
 
 unsigned long __zero_page(void)
 {
-       extern char empty_zero_page[PAGE_SIZE];
-       unsigned long dummy;
+       unsigned long page = (unsigned long) empty_zero_page;
 
-       __asm__ __volatile__(
-               ".set\tnoreorder\n\t"
-               "1:\tsw\t$0,(%0)\n\t"
-               "subu\t%1,%1,1\n\t"
-               "bne\t$0,%1,1b\n\t"
-               "addiu\t%0,%0,1\n\t"
-               ".set\treorder"
-               :"=r" (dummy),
-                "=r" (dummy)
-               :"0" ((long) empty_zero_page),
-                "1" (PTRS_PER_PAGE));
+       zeropage(page);
+       return page;
+}
 
-       return (unsigned long) empty_zero_page;
+/*
+ * This is horribly inefficient ...
+ */
+void __copy_page(unsigned long from, unsigned long to)
+{
+       /*
+        * Now copy page from uncached KSEG1 to KSEG0.  The copy destination
+        * is in KSEG0 so that we keep stupid L2 caches happy.
+        */
+       if(from == (unsigned long) empty_zero_page)
+       {
+               /*
+                * The page copied most is the COW empty_zero_page.  Since we
+                * know it's contents we can avoid the writeback reading of
+                * the page.  Speeds up the standard case alot.
+                */
+               __zeropage(to);
+       }
+       else
+       {
+               /*
+                * Force writeback of old page to memory.  We don't know the
+                * virtual address, so we have to flush the entire cache ...
+                */
+               sys_cacheflush(0, ~0, DCACHE);
+               sync_mem();
+               memcpy((void *) to,
+                      (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
+       }
+       /*
+        * Now writeback the page again if colour has changed.
+        * Actually this does a Hit_Writeback, but due to an artifact in
+        * the R4xx0 implementation this should be slightly faster.
+        * Then sweep chipset controlled secondary caches and the ICACHE.
+        */
+       if (page_colour(from) != page_colour(to))
+               sys_cacheflush(0, ~0, DCACHE);
+       sys_cacheflush(0, ~0, ICACHE);
 }
 
 void show_mem(void)
 {
-       int i,free = 0,total = 0,reserved = 0;
+       int i, free = 0, total = 0, reserved = 0;
        int shared = 0;
 
        printk("Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-       i = high_memory >> PAGE_SHIFT;
+       printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
        while (i-- > 0) {
                total++;
-               if (mem_map[i] & MAP_PAGE_RESERVED)
+               if (mem_map[i].reserved)
                        reserved++;
-               else if (!mem_map[i])
+               else if (!mem_map[i].count)
                        free++;
                else
-                       shared += mem_map[i]-1;
+                       shared += mem_map[i].count-1;
        }
-       printk("%d pages of RAM\n",total);
-       printk("%d free pages\n",free);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
+       printk("%d pages of RAM\n", total);
+       printk("%d free pages\n", free);
+       printk("%d reserved pages\n", reserved);
+       printk("%d pages shared\n", shared);
        show_buffers();
 #ifdef CONFIG_NET
        show_net_buffers();
@@ -133,56 +226,22 @@ void show_mem(void)
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
 
-/*
- * paging_init() sets up the page tables - note that the first 4MB are
- * already mapped by head.S.
- *
- * This routines also unmaps the page at virtual kernel address 0, so
- * that we can trap those pesky NULL-reference errors in the kernel.
- */
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-       pgd_t * pg_dir;
-       pte_t * pg_table;
-       unsigned long tmp;
-       unsigned long address;
-
-       start_mem = PAGE_ALIGN(start_mem);
-       address = 0;
-       pg_dir = swapper_pg_dir;
-       while (address < end_mem) {
-               if (pgd_none(pg_dir[0])) {
-                       pgd_set(pg_dir, (pte_t *) start_mem);
-                       start_mem += PAGE_SIZE;
-               }
-               /*
-                * also map it in at 0x00000000 for init
-                */
-               pg_table = (pte_t *) pgd_page(pg_dir[0]);
-               pgd_set(pg_dir, pg_table);
-               pg_dir++;
-               for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) {
-                       if (address < end_mem)
-                               set_pte(pg_table, mk_pte(address, PAGE_SHARED));
-                       else
-                               pte_clear(pg_table);
-                       address += PAGE_SIZE;
-               }
-       }
-#if KERNELBASE == KSEG0
-       cacheflush();
-#endif
-       invalidate();
+       pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
        return free_area_init(start_mem, end_mem);
 }
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
 {
        int codepages = 0;
-       int reservedpages = 0;
        int datapages = 0;
        unsigned long tmp;
-       extern int etext;
+       extern int _etext;
+
+#ifdef CONFIG_MIPS_JAZZ
+       start_mem = vdma_init(start_mem, end_mem);
+#endif
 
        end_mem &= PAGE_MASK;
        high_memory = end_mem;
@@ -190,10 +249,12 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
        /* mark usable pages in the mem_map[] */
        start_mem = PAGE_ALIGN(start_mem);
 
-       while (start_mem < high_memory) {
-               mem_map[MAP_NR(start_mem)] = 0;
-               start_mem += PAGE_SIZE;
+       tmp = start_mem;
+       while (tmp < high_memory) {
+               mem_map[MAP_NR(tmp)].reserved = 0;
+               tmp += PAGE_SIZE;
        }
+
 #ifdef CONFIG_DESKSTATION_TYNE
        deskstation_tyne_dma_init();
 #endif
@@ -203,33 +264,24 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
 #ifdef CONFIG_SOUND
        sound_mem_init();
 #endif
-       for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
-               if (mem_map[MAP_NR(tmp)]) {
-                       /*
-                        * We don't have any reserved pages on the
-                        * MIPS systems supported until now
-                        */
-                       if (0)
-                               reservedpages++;
-                       else if (tmp < ((unsigned long) &etext - KERNELBASE))
+       for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
+               if (mem_map[MAP_NR(tmp)].reserved) {
+                       if (tmp < (unsigned long) &_etext)
                                codepages++;
-                       else
+                       else if (tmp < start_mem)
                                datapages++;
                        continue;
                }
-               mem_map[MAP_NR(tmp)] = 1;
+               mem_map[MAP_NR(tmp)].count = 1;
                free_page(tmp);
        }
        tmp = nr_free_pages << PAGE_SHIFT;
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+       printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
                tmp >> 10,
-               high_memory >> 10,
+               (high_memory - PAGE_OFFSET) >> 10,
                codepages << (PAGE_SHIFT-10),
-               reservedpages << (PAGE_SHIFT-10),
                datapages << (PAGE_SHIFT-10));
-       pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
 
-       invalidate();
        return;
 }
 
@@ -243,12 +295,12 @@ void si_meminfo(struct sysinfo *val)
        val->freeram = nr_free_pages << PAGE_SHIFT;
        val->bufferram = buffermem;
        while (i-- > 0)  {
-               if (mem_map[i] & MAP_PAGE_RESERVED)
+               if (mem_map[i].reserved)
                        continue;
                val->totalram++;
-               if (!mem_map[i])
+               if (!mem_map[i].count)
                        continue;
-               val->sharedram += mem_map[i]-1;
+               val->sharedram += mem_map[i].count-1;
        }
        val->totalram <<= PAGE_SHIFT;
        val->sharedram <<= PAGE_SHIFT;
index a1fe2e76a2211f55eb06d51e3f221d98284d367b..760c63fc15bdf7c3bb6d9ff78d4c7481fbeb4f7d 100644 (file)
@@ -9,7 +9,7 @@
 
 SUB_DIRS     := block char net #streams
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sound
+ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sound cdrom
 
 ifdef CONFIG_PCI
 SUB_DIRS += pci
index 4ff973086b34c19f355cf799447f139e52e7701b..1875aca7e2dafb7b674e2a489d26a4c7933fef15 100644 (file)
@@ -16,7 +16,7 @@
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o ramdisk.o genhd.o 
+L_OBJS   := ll_rw_blk.o rd.o genhd.o 
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 
index b57c4cbded5a1ff7b8c7ab000a7a4d50ef97128e..dd3528ecf8b6f27a4885bf8c16b8006c241e0d06 100644 (file)
@@ -12,6 +12,8 @@ See description later on below for handling BIG IDE drives with >1024 cyls.
 
 Major features of ide.c & ide-cd.c:
 
+NEW!   - support for IDE ATAPI *tape* drives, courtesy of Gadi Oxman
+               (run MAKEDEV.ide to create the tape device entries in /dev/)
 NEW!   - support for up to *four* IDE interfaces on one or more IRQs
 NEW!   - support for any mix of up to *eight* disk and/or cdrom drives
        - support for reading IDE ATAPI cdrom drives (NEC,MITSUMI,VERTOS,SONY)
index 8a55caca4c23335ff847b46076d50ecd42d9e384..c0fbaab01c075efd06b0cc5f8d13235a0379cc26 100644 (file)
@@ -237,7 +237,7 @@ int ide_probe_for_cmd640x(void)
 {
        int  i;
        int  second_port;
-       int  read_ahead;
+       int  cmd_read_ahead;
        byte b;
 
        for (i = 0; i < MAX_HWIFS; i++)
@@ -287,13 +287,13 @@ int ide_probe_for_cmd640x(void)
         */
        bus_speed = (bus_type == vlb) ? 50 : 40; 
 
-#if 0  /* don't know if this is reliable yet */
+#if 1  /* don't know if this is reliable yet */
        /*
         * Enable readahead for versions above 'A'
         */
-       read_ahead = (cmd640_chip_version > 1);
+       cmd_read_ahead = (cmd640_chip_version > 1);
 #else
-       read_ahead = 0;
+       cmd_read_ahead = 0;
 #endif
        /*
         * Setup Control Register
@@ -303,7 +303,7 @@ int ide_probe_for_cmd640x(void)
                b |= CNTRL_ENA_2ND;
        else
                b &= ~CNTRL_ENA_2ND;
-       if (read_ahead)
+       if (cmd_read_ahead)
                b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
        else
                b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
@@ -314,7 +314,7 @@ int ide_probe_for_cmd640x(void)
         */
        if (second_port) {
                /* We reset timings, and setup read-ahead */
-               b = read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
+               b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
                put_cmd640_reg(cmd640_key, ARTTIM23, b);
                put_cmd640_reg(cmd640_key, DRWTIM23, 0);
        }
@@ -343,7 +343,7 @@ int ide_probe_for_cmd640x(void)
        put_cmd640_reg(cmd640_key, CMDTIM, 0);
 
        printk("\n ... serialized, %s read-ahead, secondary interface %s\n",
-              read_ahead ? "enabled" : "disabled",
+              cmd_read_ahead ? "enabled" : "disabled",
               second_port ? "enabled" : "disabled");
 
        return 1;
index c555290f607a558c013e2c5c5656f6dbcdc2fe39..a50bbb3a139211b106f58018047f57e67e06e3a6 100644 (file)
@@ -30,7 +30,6 @@ struct gendisk *gendisk_head = NULL;
 static int current_minor = 0;
 extern int *blk_size[];
 extern void rd_load(void);
-extern int ramdisk_size;
 
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
@@ -559,6 +558,5 @@ void device_setup(void)
                nr += p->nr_real;
        }
 
-       if (ramdisk_size)
-               rd_load();
+       rd_load();
 }
index 08465d92a5c28cacf051554ff2d7019f646acd2a..71684835f9189dbd77962a105208bf1f14841d00 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.c      Version 1.0 - ALPHA     Dec  3, 1995
+ * linux/drivers/block/ide-tape.c      Version 1.1 - ALPHA     Dec  14, 1995
  *
  * Copyright (C) 1995 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  *
  * This driver is a part of the Linux ide driver and works in co-operation
  * with linux/drivers/block/ide.c.
  *
- * This driver provides both a block device and a character device interface to
- * the tape. The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device interface,
- * on the other hand, creates new requests, adds them to the request-list
- * of the block device, and waits for their completion.
+ * The driver, in co-operation with ide.c, basically traverses the 
+ * request-list for the block device interface. The character device
+ * interface, on the other hand, creates new requests, adds them
+ * to the request-list of the block device, and waits for their completion.
+ *
+ * Pipelined operation mode is now supported on writes.
  *
  * The block device major and minor numbers are determined from the
- * tape relative position in the ide interfaces, as explained in ide.c.
+ * tape's relative position in the ide interfaces, as explained in ide.c.
  *
  * The character device interface consists of two devices:
  *
  * Run /usr/src/linux/drivers/block/MAKEDEV.ide to create the above entries.
  * We currently support only one ide tape drive.
  *
- * Although we do support requests which originate from the buffer cache to
- * some extent, it is recommended to use the character device interface when
- * performing a long read or write operation (relative to the amount of free
- * memory in your system). Otherwise, free memory will be used to cache tape
- * blocks, those cached blocks won't be used, Linux's responsiveness will
- * suffer as we start to swap.
- *
  * The general magnetic tape commands compatible interface, as defined by
  * include/linux/mtio.h, is accessible through the character device.
- * Our own ide-tape ioctl's can can be issued to either the block device or
- * the character device.
  *
- * Opening the block device interface will be refused by default.
+ * General ide driver configuration options, such as the interrupt-unmask
+ * flag, can be configured by issuing an ioctl to the block device interface,
+ * as any other ide device.
+ *
+ * Our own ide-tape ioctl's can can be issued to either the block device or
+ * the character device interface.
  *
  * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
  *
  *                        performing one tape r/w request, a lot of requests
  *                        from the other device can be queued and ide.c will
  *                       service all of them after this single tape request.
- * Ver 1.0   ???         Integrated into Linux 1.3.??? development tree.
+ * Ver 1.0   Dec 11 95   Integrated into Linux 1.3.46 development tree.
  *                       On each read / write request, we now ask the drive
  *                        if we can transfer a constant number of bytes
  *                        (a parameter of the drive) only to its buffers,
  *                        without causing actual media access. If we can't,
  *                        we just wait until we can by polling the DSC bit.
  *                        This ensures that while we are not transferring
- *                        more bytes than the constant reffered to above, the
+ *                        more bytes than the constant referred to above, the
  *                        interrupt latency will not become too high and
  *                        we won't cause an interrupt timeout, as happened
  *                        occasionally in the previous version.
  *                       Our data transfer buffer is allocated on startup,
  *                        rather than before each data transfer. This should
  *                        ensure that we will indeed have a data buffer.
+ * Ver 1.1   Dec 14 95   Fixed random problems which occured when the tape
+ *                        shared an interface with another device.
+ *                        (poll_for_dsc was a complete mess).
+ *                       Removed some old (non-active) code which had
+ *                        to do with supporting buffer cache originated
+ *                        requests.
+ *                       The block device interface can now be opened, so
+ *                        that general ide driver features like the unmask
+ *                        interrupts flag can be selected with an ioctl.
+ *                        This is the only use of the block device interface.
+ *                       New fast pipelined operation mode (currently only on
+ *                        writes). When using the pipelined mode, the
+ *                        throughput can potentially reach the maximum
+ *                        tape supported throughput, regardless of the
+ *                        user backup program. On my tape drive, it sometimes
+ *                        boosted performance by a factor of 2. Pipelined
+ *                        mode is enabled by default, but since it has a few
+ *                        downfalls as well, you may want to disable it.
+ *                        A short explanation of the pipelined operation mode
+ *                        is available below.
  *
  * We are currently in an *alpha* stage. The driver is not complete and not
  * much tested. I would strongly suggest to:
  *
  */
 
+/*
+ * A short explanation of the pipelined operation mode.
+ *
+ * Pipelined mode is currently only implemented on writes. Reads are still
+ * performed in the slow non-pipelined mode.
+ *
+ * The pipeline mode, when enough pipeline stages are available, manages to
+ * keep the tape constantly streaming with the maximum device supported
+ * throughput, regardless of the user backup program, since even when Linux
+ * is busy doing other tasks, we still have job to be done.
+ *
+ * On my tape drive, using pipelined mode and giving the tape its own
+ * interface and irq, I get a constant over 400 KBps throughput, which seems
+ * to be the maximum throughput supported by my tape. When sharing the
+ * interface between the tape and another ata-2 disk drive, I receive around
+ * 350 KBps.
+ *
+ * Using the non-pipelined mode, I get anything between 150 to 380 KBps,
+ * with the average being around 150 or 250 KBps, depending mainly on
+ * the double buffering capabilities of the user backup program, but also
+ * on some additional factors, such as the user block size and the ongoing
+ * disk activity.
+ *
+ * However, there are some downfalls:
+ *
+ *     1.      We use memory (for data buffers) in proportional to the number
+ *             of pipeline stages (each stage is about 26 KB with my tape).
+ *     2.      We cheat and postpone error codes to the user task. Again,
+ *             the postponing period is proportional to the number of stages.
+ *
+ * Concerning (1):
+ *
+ *     1.      We allocate stages dynamically only when we need them. When
+ *             we don't need them, we don't consume additional memory. In
+ *             case we can't allocate stages, we just manage without them
+ *             (at the expense of decreased throughput) so when Linux is
+ *             tight in memory, we will not pose additional difficulties.
+ *
+ *     2.      The maximum number of stages (which is, in fact, the maximum
+ *             amount of memory) which we allocate is limited by the compile
+ *             time parameter IDETAPE_MAX_PIPELINE_STAGES.
+ *
+ *     3.      The maximum number of stages is a controlled parameter - We
+ *             don't start from the user defined maximum number of stages
+ *             but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
+ *             will not even allocate this amount of stages if the user
+ *             program can't handle the speed). We then implement a feedback
+ *             loop which checks if the pipeline is empty, and if it is, we
+ *             increase the maximum number of stages as necessary until we
+ *             reach the optimum value which just manages to keep the tape
+ *             busy with with minimum allocated memory or until we reach
+ *             IDETAPE_MAX_PIPELINE_STAGES.
+ *
+ * Concerning (2):
+ *
+ *     In pipelined mode, ide-tape can not return accurate error codes to
+ *      the user program since we usually just add the request to the
+ *      pipeline without waiting for it to be serviced. In case an error
+ *      occurs, I will report it on the next user request.
+ *
+ *     For accurate error codes, you should disable pipelined mode.
+ *
+ * You can enable/disable/tune the pipelined operation mode by adjusting
+ * the compile time parameters in ide-tape.h.
+ */
 #include <linux/hdreg.h>
 #include <linux/types.h>
 #include <linux/string.h>
 /*
  *     Main Linux ide driver include file
  *
- *     Automatically includes our first include file - ide-tape1.h.
+ *     Automatically includes our include file - ide-tape.h.
  */
  
 #include "ide.h"               
  *
  */
 
+#define        IDETAPE_FIRST_REQUEST                   90
+
 /*
  *     IDETAPE_PACKET_COMMAND_REQUEST_TYPE1 is used to queue a packet command
  *     in the request queue. We will wait for DSC before issuing the command
 #define        IDETAPE_READ_REQUEST                    92
 #define        IDETAPE_WRITE_REQUEST                   93
 
+#define IDETAPE_LAST_REQUEST                   93
+
+/*
+ *     A macro which can be used to check if a we support a given
+ *     request command.
+ */
+
+#define IDETAPE_REQUEST_CMD(cmd)       ((cmd >= IDETAPE_FIRST_REQUEST) && (cmd <= IDETAPE_LAST_REQUEST))
+
 /*
  *     We are now able to postpone an idetape request in the stage
  *     where it is polling for DSC and service requests from the other
@@ -629,7 +723,7 @@ void idetape_pc_intr (ide_drive_t *drive);
  
 void idetape_postpone_request (ide_drive_t *drive);
 void idetape_poll_for_dsc (unsigned long data);
-void idetape_put_back_postponed_request (ide_drive_t *drive);
+void idetape_poll_for_dsc_direct (unsigned long data);
 void idetape_media_access_finished (ide_drive_t *drive);
 
 /*
@@ -695,10 +789,29 @@ void idetape_chrdev_release (struct inode *inode,struct file *file);
  */
  
 int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count);
+
+/*
+ *     idetape_add_chrdev_write_request adds a character device write
+ *     request to the pipeline.
+ */
+int idetape_add_chrdev_write_request (ide_drive_t *drive,int cmd,int blocks,char *buffer);
+
+/*
+ *     idetape_queue_rw_tail will add a command to the tail of the device
+ *     request queue and wait for it to finish. This is used when we
+ *     can not allocate pipeline stages (or in non-pipelined mode).
+ */
 int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer);
+
+/*
+ *     Adds a packet command request to the tail of the device request
+ *     queue and waits for it to be serviced.
+ */
 int idetape_queue_pc_tail (ide_drive_t *drive,idetape_packet_command_t *pc);
 
-void idetape_fake_read (ide_drive_t *drive);
 int idetape_position_tape (ide_drive_t *drive,unsigned long block);
 int idetape_rewind_tape (ide_drive_t *drive);
 
@@ -712,10 +825,23 @@ void idetape_get_mode_sense_results (ide_drive_t *drive);
  *     General utility functions
  */
  
-void idetape_fixstring (byte *s, const int bytecount, const int byteswap);
 unsigned long idetape_swap_long (unsigned long temp);
 unsigned short idetape_swap_short (unsigned short temp);
 
+/*
+ *     Pipeline related functions
+ */
+
+idetape_pipeline_stage_t *idetape_kmalloc_stage (ide_drive_t *drive);
+void idetape_kfree_stage (idetape_pipeline_stage_t *stage);
+void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer);
+void idetape_copy_buffer_to_stage (idetape_pipeline_stage_t *stage,char *buffer);
+void idetape_increase_max_pipeline_stages (ide_drive_t *drive);
+void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage);
+void idetape_active_next_stage (ide_drive_t *drive);
+void idetape_empty_pipeline (ide_drive_t *drive);
+void idetape_insert_pipeline_into_queue (ide_drive_t *drive);
+
 /*
  *     For general magnetic tape device compatibility.
  */
@@ -972,37 +1098,62 @@ void idetape_register_chrdev (void)
 void idetape_setup (ide_drive_t *drive)
 
 {
-       int buffer_size;
        idetape_tape_t *tape=&(drive->tape);
-
+       unsigned int allocation_length;
+       
 #if IDETAPE_DEBUG
        printk ("ide-tape: Reached idetape_setup\n");
 #endif /* IDETAPE_DEBUG */     
        
        drive->ready_stat = 0;                  /* With an ATAPI device, we can issue packet commands */
                                                /* regardless of the state of DRDY */
+       HWIF(drive)->tape_drive=drive;
+
        tape->block_address=0;                  
        tape->block_address_valid=0;
-       tape->locate_to=0;
-       tape->locate_retries=0;
        tape->pc_stack_index=0;
        tape->failed_pc=NULL;
        tape->postponed_rq=NULL;
-       tape->last_written_valid=0;
        tape->busy=0;
+       tape->active_data_request=NULL;
+       tape->current_number_of_stages=0;
+       tape->first_stage=tape->last_stage=NULL;
+       tape->pipeline_was_full_once=0;
+       tape->error_in_pipeline_stage=0;
+       tape->pipeline_locked=0;
+
+       tape->request_status=0;
+       tape->request_dsc_callback=0;
        
+#if IDETAPE_PIPELINE
+       tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
+       printk ("ide-tape: Operating in pipelined (fast and tricky) write mode.\n");
+#else
+       tape->max_number_of_stages=0;
+       printk ("ide-tape: Operating in non-pipelined (slow and safe) write mode.\n");
+#endif /* IDETAPE_PIPELINE */
+       printk ("ide-tape: Operating in non-pipelined (slow and safe) read mode.\n");
+
        idetape_get_mode_sense_results (drive);
 
-       buffer_size=tape->capabilities.ctl*tape->tape_block_size;
-       tape->data_buffer=kmalloc (buffer_size,GFP_KERNEL);
-       if (tape->data_buffer == NULL) {
-               printk ("ide-tape: FATAL - Can not allocate %d bytes for data transfer buffer\n",buffer_size);
+       tape->data_buffer_size=tape->capabilities.ctl*tape->tape_block_size;
+
+       allocation_length=tape->data_buffer_size;
+       if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
+               allocation_length+=IDETAPE_ALLOCATION_BLOCK;
+       
+       tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL);
+       tape->temp_data_buffer=kmalloc (allocation_length,GFP_KERNEL);
+       if (tape->data_buffer == NULL || tape->temp_data_buffer == NULL) {
+               printk ("ide-tape: FATAL - Can not allocate 2 buffers of %d bytes each\n",allocation_length);
                printk ("ide-tape: Aborting character device installation\n");
                idetape_drive_already_found=0;
                unregister_chrdev (idetape_chrdev.major,idetape_chrdev.name);
                return;
        }
-       printk ("ide-tape: Speed - %d KBps. Recommended transfer unit - %d bytes.\n",tape->capabilities.speed,buffer_size);
+
+       printk ("ide-tape: Tape speed - %d KBps. Recommended transfer unit - %d bytes.\n",tape->capabilities.speed,tape->data_buffer_size);
+
        return;
 }
 
@@ -1129,7 +1280,7 @@ void idetape_issue_packet_command  (ide_drive_t *drive,idetape_packet_command_t
 
        tape=&(drive->tape);
                
-#ifdef IDETAPE_DEBUG
+#if IDETAPE_DEBUG
        if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
                printk ("ide-tape: ide-tape.c bug - Two request sense in serial were issued\n");
                /* ??? Need to rethink about that */            
@@ -1262,7 +1413,7 @@ void idetape_pc_intr (ide_drive_t *drive)
                if (pc->callback==NULL)                 
                        printk ("ide-tape: ide-tape bug - Callback function not set !\n");
                else
-#endif IDETAPE_DEBUG
+#endif /* IDETAPE_DEBUG */
                        (*pc->callback)(drive);                 /* Command finished - Call the callback function */
                return;
        }
@@ -1334,16 +1485,19 @@ void idetape_postpone_request (ide_drive_t *drive)
        idetape_tape_t *tape;
        unsigned long flags;
        struct request *rq;
-               
+       idetape_status_reg_t status;
+       
        tape=&(drive->tape);
+       status.all=IN_BYTE (IDETAPE_STATUS_REG);
 
+       sti ();
+       
 #if IDETAPE_DEBUG
        printk ("Reached idetape_postpone_request\n");
        if (tape->postponed_rq != NULL)
                printk ("ide-tape.c bug - postponed_rq not NULL in idetape_postpone_request\n");
 #endif /* IDETAPE_DEBUG */
 
-       tape->dsc_count=0;
        tape->dsc_timer.expires=jiffies + tape->dsc_polling_frequency;  /* Set timer to poll for */
        tape->dsc_timeout=jiffies+IDETAPE_DSC_TIMEOUT;                  /* actual completion */
        tape->dsc_timer.data=(unsigned long) drive;
@@ -1353,61 +1507,55 @@ void idetape_postpone_request (ide_drive_t *drive)
        /*
         * Remove current request from the request queue:
         */
-       save_flags(flags);                                              /* Let ide.c handle another request */
-       cli();
+
        tape->postponed_rq = rq = HWGROUP(drive)->rq;
        rq->rq_status = IDETAPE_RQ_POSTPONED;   
+       save_flags(flags);cli ();                                       /* Let ide.c handle another request */
        blk_dev[MAJOR(rq->rq_dev)].current_request = rq->next;
        HWGROUP(drive)->rq = NULL;
        restore_flags(flags);
-
-       tape->dsc_polling_start=jiffies;        
+       
+       tape->request_status=0;
+       tape->request_dsc_callback=0;
+       tape->last_status=status.all;
+       
+       tape->dsc_polling_start=jiffies;
        add_timer(&(tape->dsc_timer));          /* Activate the polling timer */
 }
 
-
 /*
- *     idetape_poll_for_dsc gets invoked by a timer (which was set
- *     by idetape_postpone_request) to poll for the DSC bit
- *     in the status register. When the DSC bit is set, or a timeout is
- *     reached, we put back the postponed request in front of the request
- *     queue.
+ *     idetape_poll_for_dsc_direct is called from idetape_poll_for_dsc
+ *     to handle the case in which we can safely communicate with the tape
+ *     (since no other request for this hwgroup is active).
  */
  
-void idetape_poll_for_dsc (unsigned long data)
+void idetape_poll_for_dsc_direct (unsigned long data)
 
 {
-       ide_drive_t *drive;
-       idetape_tape_t *tape;
-       
+       ide_drive_t *drive=(ide_drive_t *) data;
+       ide_hwgroup_t *hwgroup=HWGROUP (drive);
+       idetape_tape_t *tape=&(drive->tape);
        idetape_status_reg_t status;
-       idetape_packet_command_t *pc;
+       unsigned long flags;
 
-       drive=(ide_drive_t *) data;
-       tape=&(drive->tape);
-       pc=tape->pc;
-       
 #if IDETAPE_DEBUG
-       printk ("%s: idetape_poll_for_dsc called\n",drive->name);
+       printk ("%s: idetape_poll_for_dsc_direct called\n",drive->name);
 #endif /* IDETAPE_DEBUG */     
 
+       save_flags (flags);cli ();
+       OUT_BYTE(drive->select.all,IDE_SELECT_REG);
        status.all=IN_BYTE (IDETAPE_STATUS_REG);
+       if (hwgroup->drive != NULL)
+               OUT_BYTE (hwgroup->drive->select.all,IDE_SELECT_REG);
+       restore_flags (flags);
 
-       if (status.b.dsc)
-               tape->dsc_count++;
-       else {
-               if (tape->dsc_count)
-                       printk ("ide-tape: DSC fluctuation detected - Restarting DSC count\n");
-               tape->dsc_count=0;
-       }
-
-       if (tape->dsc_count == IDETAPE_DSC_COUNT) {             /* DSC received */
+       if (status.b.dsc) {                                     /* DSC received */
                tape->dsc_received=1;
                del_timer (&(tape->dsc_timer));                 /* Stop polling and put back the postponed */
                idetape_put_back_postponed_request (drive);     /* request in the request queue */
                return;
        }
-               
+
        if (jiffies > tape->dsc_timeout)        { /* Timeout */
                tape->dsc_received=0;
                del_timer (&(tape->dsc_timer));
@@ -1415,23 +1563,129 @@ void idetape_poll_for_dsc (unsigned long data)
                idetape_put_back_postponed_request (drive);
                return;
        }
-       
+
        /* Poll again */
+       
+       if (jiffies - tape->dsc_polling_start > IDETAPE_FAST_SLOW_THRESHOLD)
+               tape->dsc_timer.expires = jiffies + IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY;
+       else
+               tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency;
+       add_timer(&(tape->dsc_timer));
+       return;
+}
+
+/*
+ *     idetape_poll_for_dsc gets invoked by a timer (which was set
+ *     by idetape_postpone_request) to poll for the DSC bit
+ *     in the status register.
+ *
+ *     We take care not to perform any tape access and not to touch the
+ *     device request queue if the driver is accessing the other device.
+ *     We will instead ask ide.c to perform those functions on the next
+ *     call to do_request, at the point in which the other device is idle.
+ *
+ *     However, in case the other device is already idle, we will read
+ *     the status register from our timer handler.
+ *
+ *     I am also a bit paranoid with the use of cli (), all through the
+ *     code. I still need to think harder about each one whether we can
+ *     avoid it and still be free of race conditions ...
+ */
+void idetape_poll_for_dsc (unsigned long data)
 
+{
+       ide_drive_t *drive=(ide_drive_t *) data;
+       unsigned int major = HWIF(drive)->major;
+       idetape_tape_t *tape=&(drive->tape);
+       struct blk_dev_struct *bdev = &blk_dev[major];
+       unsigned long flags;
+       
+       idetape_status_reg_t status;
+
+       save_flags (flags);cli ();
+                       
+#if IDETAPE_DEBUG
+       printk ("%s: idetape_poll_for_dsc called\n",drive->name);
+#endif /* IDETAPE_DEBUG */     
+
+       /*
+        *      Check if the other device is idle. If there are no requests,
+        *      we can safely access the tape.
+        */
+
+       if (bdev->current_request == NULL) {
+               restore_flags (flags);
+               idetape_poll_for_dsc_direct (data);
+               return;
+       }
+       
+       if (bdev->current_request->next == NULL) {
+               /*
+                *      There will not be another request after the currently
+                *      ongoing request, so ide.c won't be able to sample
+                *      the status register on our behalf in do_request. Just
+                *      give up and poll again (in a faster frequency), until
+                *      we are lucky.
+                */
+               restore_flags (flags);
+               tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency/2;
+               add_timer(&(tape->dsc_timer));
+               return;
+       }
+       
+       /*
+        *      We now know that:
+        *
+        *              1.      The ide driver is potentially accessing
+        *                      the other device -- We can not touch it.
+        *              2.      do_request will be called after the current
+        *                      request is finished.
+        *
+        *      We will therefor ask ide.c to perform the tasks on our behalf.
+        */
+        
+       status.all=tape->last_status;
+       
+       if (status.b.dsc) {                                     /* DSC received */
+               tape->dsc_received=1;
+               del_timer (&(tape->dsc_timer));                 /* Stop polling and request ide.c to call */
+               tape->request_dsc_callback=1;                   /* our idetape_put_back_postponed_request later */
+               restore_flags (flags);          
+               return;
+       }
+
+       if (jiffies > tape->dsc_timeout)        {               /* Timeout */
+               tape->dsc_received=1;
+               del_timer (&(tape->dsc_timer));
+               /* ??? */
+               tape->request_dsc_callback=1;
+               restore_flags (flags);
+               return;
+       }
+
+       /*
+        *      Request ide.c to sample for us the tape's status register on
+        *      the next time in which it can be safely done.
+        */
+
+       tape->request_status=1;
+       restore_flags (flags);
+                
+       /* Poll again */
+       
        if (jiffies - tape->dsc_polling_start > IDETAPE_FAST_SLOW_THRESHOLD)
                tape->dsc_timer.expires = jiffies + IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY;
        else
                tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency;
-/*     init_timer (&(tape->dsc_timer)); */
        add_timer(&(tape->dsc_timer));
        return;
 }
 
 /*
- *     idetape_put_back_postponed_request gets called by
- *     idetape_poll_for_dsc when we decided to stop polling - Either
- *     becase we received DSC or because we decided to give up and
- *     stop waiting.
+ *     idetape_put_back_postponed_request gets called by do_request
+ *     in ide.c when we decided to stop polling for DSC and continue
+ *     servicing our postponed request.
  */
 
 void idetape_put_back_postponed_request (ide_drive_t *drive)
@@ -1571,7 +1825,7 @@ void idetape_read_callback (ide_drive_t *drive)
 #if IDETAPE_DEBUG      
        printk ("ide-tape: Reached idetape_read_callback\n");
 #endif /* IDETAPE_DEBUG */
-       tape->block_address+=tape->pc->actually_transferred/512;
+       tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
        if (!tape->pc->error) {
 #if IDETAPE_DEBUG
                printk ("Request completed\n");
@@ -1588,33 +1842,6 @@ void idetape_read_callback (ide_drive_t *drive)
        return;
 }
 
-void idetape_fake_read (ide_drive_t *drive)
-
-{
-       idetape_tape_t *tape;
-       struct request *rq;
-       unsigned long i;
-
-       tape=&(drive->tape);    
-       rq=HWGROUP(drive)->rq;
-#if IDETAPE_DEBUG      
-       printk ("ide-tape: Reached idetape_fake_read\n");
-#endif /* IDETAPE_DEBUG */
-
-#if IDETAPE_DEBUG
-       printk ("Request completed\n");
-#endif /* IDETAPE_DEBUG */
-       
-       for (i=0;i<rq->current_nr_sectors*512;i++)
-               rq->buffer [i]=0;
-
-       tape->block_address+=rq->current_nr_sectors;
-       rq->sector+=rq->current_nr_sectors;
-       rq->nr_sectors-=rq->current_nr_sectors;
-       rq->current_nr_sectors=0;
-       idetape_end_request (1,HWGROUP (drive));
-}
-
 void idetape_write_callback (ide_drive_t *drive)
 
 {
@@ -1626,7 +1853,7 @@ void idetape_write_callback (ide_drive_t *drive)
 #if IDETAPE_DEBUG      
        printk ("ide-tape: Reached idetape_write_callback\n");
 #endif /* IDETAPE_DEBUG */
-       tape->block_address+=tape->pc->actually_transferred/512;
+       tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
        if (!tape->pc->error) {
 #if IDETAPE_DEBUG
                printk ("Request completed\n");
@@ -1743,9 +1970,9 @@ void idetape_display_inquiry_result (byte *buffer)
        idetape_inquiry_result_t *result;
 
        result=(idetape_inquiry_result_t *) buffer;
-       idetape_fixstring (result->vendor_id,8,0);
-       idetape_fixstring (result->product_id,16,0);
-       idetape_fixstring (result->revision_level,4,0);
+       ide_fixstring (result->vendor_id,8,0);
+       ide_fixstring (result->product_id,16,0);
+       ide_fixstring (result->revision_level,4,0);
 
        if (result->response_format != 2) {
                printk ("The INQUIRY Data Format is unknown to us !\n");
@@ -2258,26 +2485,54 @@ void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
 {
        ide_drive_t *drive = hwgroup->drive;
        struct request *rq = hwgroup->rq;
-
-       if (rq->cmd == READ || rq->cmd == WRITE) {      /* Buffer cache originated request */
-               ide_end_request (uptodate,hwgroup);     /* Let the common code handle it */
-               return;
-       }
+       idetape_tape_t *tape = &(drive->tape);
+       
                                                        /* Our own originated request */
        rq->errors=!uptodate;                           /* rq->errors will tell us if the request was successfull */
-       ide_end_drive_cmd (drive, 0, 0);
+       
+       if (tape->active_data_request == rq) {          /* The request was a data transfer request */
+#if IDETAPE_DEBUG
+               if (!tape->max_number_of_stages)
+                       printk ("ide-tape: non pipelined mode bug\n");
+               printk ("Finished our active data request\n");
+               printk ("Requests in pipeline: %d\n",tape->current_number_of_stages);
+#endif /* IDETAPE_DEBUG */
+               if (rq->errors)
+                       tape->error_in_pipeline_stage=1;
 
-       /* The "up(rq->sem);" does the necessary "wake_up()" for us,
-        * providing we started sleeping with a "down()" call.
-        * This may not be the case if the driver converts a READ or WRITE
-        * request into a special internal rq->cmd type.   -ml
-        */
-        
-        /*
-         * As Mark explained, we do not need a "wake_up()" call here,
-         * since we are always sleeping with a "down()" call.
-         */
+               /*
+                *      Pass to the next stage, but avoid a possible
+                *      race condition which could occur since
+                *      active_data_request is set to NULL until
+                *      idetape_active_next_stage returns, and in that
+                *      time, the higher level of the driver can get
+                *      an inaccurate sampling of this variable.
+                */
+                
+               tape->pipeline_locked=1;
+               tape->active_data_request = NULL;
+               if (tape->first_stage == NULL) {
+                       tape->pipeline_locked=0;
+                       idetape_increase_max_pipeline_stages (drive);
+                       return;
+               }
+               idetape_active_next_stage (drive);
+               tape->pipeline_locked=0;
+#if IDETAPE_DEBUG
+               printk ("Using ide_end\n");
+#endif /* IDETAPE_DEBUG */
 
+               /*
+                *      Insert the next request into the request queue.
+                *
+                *      We currently give higher priority to the other devie
+                *      by using ide_end. ide_next can be used to give us
+                *      a higher priority.
+                */
+                
+               ide_do_drive_cmd (drive,tape->active_data_request,ide_end);
+       }
+       ide_end_drive_cmd (drive, 0, 0);
 }
 
 /*
@@ -2287,19 +2542,33 @@ void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
 void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
 
 {
-       idetape_tape_t *tape;
+       idetape_tape_t *tape=&(drive->tape);
        idetape_packet_command_t *pc;
-       struct request *new_rq;
        idetape_status_reg_t status;
 
-       tape=&(drive->tape);
-               
 #if IDETAPE_DEBUG
        printk ("Current request:\n");
        printk ("rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
        printk ("sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDETAPE_DEBUG */
 
+       if (!IDETAPE_REQUEST_CMD (rq->cmd)) {
+
+               /*
+                *      We do not support buffer cache originated requests.
+                */
+
+               printk ("ide-tape: Unsupported command in request queue\n");
+               printk ("ide-tape: The block device interface should not be used for data transfers.\n");
+               printk ("ide-tape: Use the character device interfaces\n");
+               printk ("ide-tape: /dev/ht0 and /dev/nht0 instead.\n");
+               printk ("ide-tape: (Run linux/drivers/block/MAKEDEV.ide to create them)\n");
+               printk ("ide-tape: Aborting request.\n");
+
+               ide_end_request (0,HWGROUP (drive));                    /* Let the common code handle it */
+               return;
+       }
+
        /* Retry a failed packet command */
 
        if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
@@ -2310,13 +2579,13 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
        /* Check if we have a postponed request */
        
        if (tape->postponed_rq != NULL) {
-/* #if IDETAPE_DEBUG */
+ #if IDETAPE_DEBUG
                if (tape->postponed_rq->rq_status != RQ_ACTIVE || rq != tape->postponed_rq) {
                        printk ("ide-tape: ide-tape.c bug - Two DSC requests were queued\n");
                        idetape_end_request (0,HWGROUP (drive));
                        return;
                }
-/* #endif */ /* IDETAPE_DEBUG */
+#endif /* IDETAPE_DEBUG */
                if (rq->cmd == IDETAPE_PACKET_COMMAND_REQUEST_TYPE1) {
        
                        /* Media access command */
@@ -2335,69 +2604,10 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
                 tape->postponed_rq = NULL;
        }       
        
-
-       if (rq->cmd == READ || rq->cmd == IDETAPE_READ_REQUEST || rq->cmd == WRITE || rq->cmd == IDETAPE_WRITE_REQUEST) {
-
-               if (!tape->block_address_valid || tape->block_address!=rq->sector) {            /* Re-position the tape */
-               
-                       if (tape->locate_to == rq->sector && tape->locate_retries > IDETAPE_LOCATE_RETRIES) {
-                               printk ("ide-tape: Can not reach block %lu - Aborting request\n",rq->sector);
-                               tape->locate_retries=0;
-                               idetape_end_request (0,HWGROUP (drive));
-                               return;
-                       }
-                                               
-                       if (tape->locate_to == rq->sector)
-                               tape->locate_retries++;
-                       else {
-                               tape->locate_to=rq->sector;
-                               tape->locate_retries=1;
-                       }
-#if IDETAPE_DEBUG
-                       printk ("ide-tape: We are not at the requested block\n");
-                       printk ("ide-tape: Re-positioning tape\n");
-                       printk ("ide-tape: Adding READ POSITION command to the head of the queue\n");
-#endif /* IDETAPE_DEBUG */
-                       pc=idetape_next_pc_storage (drive);
-                       new_rq=idetape_next_rq_storage (drive);
-                       idetape_create_read_position_cmd (pc); 
-                       pc->buffer=pc->temp_buffer;
-                       pc->buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
-                       pc->current_position=pc->temp_buffer;
-                       idetape_queue_pc_head (drive,pc,new_rq);
-#if IDETAPE_DEBUG                      
-                       printk ("ide-tape: Adding LOCATE %lu command to the head of the queue\n",rq->sector);
-#endif /* IDETAPE_DEBUG */
-                       pc=idetape_next_pc_storage (drive);
-                       new_rq=idetape_next_rq_storage (drive);
-                       idetape_create_locate_cmd (pc,rq->sector,0);
-                       idetape_queue_pc_head (drive,pc,new_rq);
-
-                       if (!tape->block_address_valid) {               /* The tape doesn't know the position - help it */
-                                                                       /* by rewinding the tape */
-#if IDETAPE_DEBUG                      
-                               printk ("ide-tape: Adding LOCATE 0 command to the head of the queue\n");
-#endif /* IDETAPE_DEBUG */
-                               pc=idetape_next_pc_storage (drive);
-                               new_rq=idetape_next_rq_storage (drive);
-                               idetape_create_locate_cmd (pc,0,0);
-                               idetape_queue_pc_head (drive,pc,new_rq);
-                       }
-                       
-                       return;
-               }
-               else
-                       tape->locate_retries=0;
-       }
-       
        switch (rq->cmd) {
-               case READ:
                case IDETAPE_READ_REQUEST:
 #if IDETAPE_DEBUG
-                       if (rq->cmd == READ)
-                               printk ("ide-tape: Handling buffer cache READ request\n");
-                       else
-                               printk ("ide-tape: Handling our own (not buffer cache originated) READ request\n");
+                       printk ("ide-tape: Handling our own (not buffer cache originated) READ request\n");
 #endif /* IDETAPE_DEBUG */                     
                        status.all=IN_BYTE (IDETAPE_STATUS_REG);
                        if (!status.b.dsc) {                            /* Tape buffer not ready to accept r/w command */
@@ -2409,27 +2619,21 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
                                return;
                        }                       
 
-                       tape->last_written_valid=0;
-                       
                        pc=idetape_next_pc_storage (drive);
 
                        idetape_create_read_cmd (pc,rq->current_nr_sectors);
                        
                        pc->buffer=rq->buffer;
-                       pc->buffer_size=rq->current_nr_sectors*512;
+                       pc->buffer_size=rq->current_nr_sectors*tape->tape_block_size;
                        pc->current_position=rq->buffer;
-                       pc->request_transfer=rq->current_nr_sectors*512;
+                       pc->request_transfer=rq->current_nr_sectors*tape->tape_block_size;
 
                        idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
                        return;
                
-               case WRITE:
                case IDETAPE_WRITE_REQUEST:
 #if IDETAPE_DEBUG
-                       if (rq->cmd == WRITE)
-                               printk ("ide-tape: Handling buffer cache WRITE request\n");
-                       else
-                               printk ("ide-tape: Handling our own (not buffer cache originated) WRITE request\n");
+                       printk ("ide-tape: Handling our own (not buffer cache originated) WRITE request\n");
 #endif /* IDETAPE_DEBUG */                     
 
                        status.all=IN_BYTE (IDETAPE_STATUS_REG);
@@ -2442,17 +2646,14 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
                                return;
                        }                       
 
-                       tape->last_written_valid=1;
-                       tape->last_written_block=rq->sector;
-                       
                        pc=idetape_next_pc_storage (drive);
 
                        idetape_create_write_cmd (pc,rq->current_nr_sectors);
                        
                        pc->buffer=rq->buffer;
-                       pc->buffer_size=rq->current_nr_sectors*512;
+                       pc->buffer_size=rq->current_nr_sectors*tape->tape_block_size;
                        pc->current_position=rq->buffer;
-                       pc->request_transfer=rq->current_nr_sectors*512;
+                       pc->request_transfer=rq->current_nr_sectors*tape->tape_block_size;
 
                        idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
                        return;
@@ -2468,7 +2669,7 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
                        if (!status.b.dsc) {                            /* Tape buffers are still not ready */
 #if IDETAPE_DEBUG
                                printk ("ide-tape: DSC != 1 - Postponing packet command request\n");
-#endif IDETAPE_DEBUG
+#endif /* IDETAPE_DEBUG */
                                rq->cmd=IDETAPE_PACKET_COMMAND_REQUEST_TYPE2;   /* Note that we are waiting for DSC *before* we */
                                                                                /* even issued the command */
                                tape->dsc_polling_frequency=IDETAPE_DSC_READ_WRITE_FREQUENCY;
@@ -2479,10 +2680,11 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b
                        pc=(idetape_packet_command_t *) rq->buffer;
                        idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
                        return;
-
+#if IDETAPE_DEBUG
                default:
-                       printk ("ide-tape: Unknown command in request - Aborting request\n");
+                       printk ("ide-tape: bug in IDETAPE_REQUEST_CMD macro\n");
                        idetape_end_request (0,HWGROUP (drive));
+#endif /* IDETAPE_DEBUG */
        }       
 }
 
@@ -2546,6 +2748,19 @@ void idetape_queue_pc_head (ide_drive_t *drive,idetape_packet_command_t *pc,stru
        (void) ide_do_drive_cmd (drive, rq, ide_preempt);
 }
 
+void idetape_wait_for_request (struct request *rq)
+
+{
+       unsigned long flags;
+       struct semaphore sem = MUTEX_LOCKED;
+
+       save_flags (flags);cli ();
+       rq->sem=&sem;
+       restore_flags (flags);
+
+       down (&sem);
+}
+
 /*
  *     idetape_queue_rw_tail is typically called from the character device
  *     interface to generate a read/write request for the block device interface
@@ -2573,40 +2788,133 @@ int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer)
        rq.sector = tape->block_address;
        rq.nr_sectors = blocks;
        rq.current_nr_sectors = blocks;
+       tape->active_data_request=NULL; /* Non-pipelined mode */
+#if IDETAPE_DEBUG
+               printk ("Using ide_tail\n");
+#endif /* IDETAPE_DEBUG */
        return ide_do_drive_cmd (drive, &rq, ide_wait);
 }
 
-/*
- *     Copied from ide.c (declared static there)
+ /*
+ *     idetape_add_chrdev_write_request tries to add a character device
+ *     originated write request to our pipeline. In case we don't succeed,
+ *     we revert to non-piplined operation mode for this request.
+ *
+ *     1.      Try to allocate a new pipeline stage.
+ *     2.      If we can't, wait for more and more requests to be serviced
+ *             and try again each time.
+ *     3.      If we still can't allocate a stage, fallback to
+ *             non-pipelined operation mode for this request.
  */
 
-void idetape_fixstring (byte *s, const int bytecount, const int byteswap)
+int idetape_add_chrdev_write_request (ide_drive_t *drive,int cmd,int blocks,char *buffer)
+
 {
-       byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+       idetape_tape_t *tape = &(drive->tape);
+       idetape_pipeline_stage_t *new_stage;
+       struct request *rq;
 
-       if (byteswap) {
-               /* convert from big-endian to host byte order */
-               for (p = end ; p != s;) {
-                       unsigned short *pp = (unsigned short *) (p -= 2);
-                       *pp = ntohs(*pp);
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_add_chrdev_write_request\n");
+       printk ("Trying to allocate stage - ");
+#endif /* IDETAPE_DEBUG */
+       
+       if (tape->error_in_pipeline_stage)              /* Return a deferred error */
+               return (-EIO);
+       
+       new_stage=idetape_kmalloc_stage (drive);
+
+       /*
+        *      If we don't have a new stage, wait for more and more requests
+        *      to finish, and try to allocate after each one.
+        *
+        *      Pay special attention to possible race conditions.
+        */
+
+       while (new_stage == NULL) {
+
+               /*
+                *      Wait for the time in which we can safely inspect
+                *      tape->first_stage.
+                */
+                
+               while (tape->pipeline_locked);
+
+               if (tape->first_stage != NULL) {
+                       idetape_wait_for_request (&(tape->first_stage->rq));
+                       new_stage=idetape_kmalloc_stage (drive);
                }
+               else
+                       break;                                  /* Linux is short on memory */
+       }
+       
+       /*
+        *      If we don't have a new_stage, fallback to non-pipelined
+        *      operation mode for this request.
+        */
+                       
+       if (new_stage == NULL) {
+               if (tape->active_data_request != NULL)
+                       idetape_wait_for_request (tape->active_data_request);
+               return (idetape_queue_rw_tail (drive,cmd,blocks,buffer));
        }
 
-       /* strip leading blanks */
-       while (s != end && *s == ' ')
-               ++s;
+       rq=&(new_stage->rq);
 
-       /* compress internal blanks and strip trailing blanks */
-       while (s != end && *s) {
-               if (*s++ != ' ' || (s != end && *s && *s != ' '))
-                       *p++ = *(s-1);
-       }
+       ide_init_drive_cmd (rq);
+       rq->buffer = NULL;                      /* We will correct this when we will actually service the request */
+       rq->cmd = cmd;
+       rq->sector = tape->block_address;       /* Doesn't actually matter - We always assume sequential access */
+       rq->nr_sectors = blocks;
+       rq->current_nr_sectors = blocks;
+
+       idetape_copy_buffer_to_stage (new_stage,buffer);
+       idetape_add_stage_tail (drive,new_stage);
+
+       return (0);             
+}
+
+void idetape_empty_pipeline (ide_drive_t *drive)
+
+{
+       idetape_tape_t *tape = &(drive->tape);
+
+       tape->pipeline_was_full_once=0;
+
+       while (tape->pipeline_locked);
+       
+       if (tape->active_data_request == NULL)
+               idetape_insert_pipeline_into_queue (drive);             
+
+       if (tape->last_stage != NULL)
+               idetape_wait_for_request (&(tape->last_stage->rq));
+
+       else if (tape->active_data_request != NULL)
+               idetape_wait_for_request (tape->active_data_request);
 
-       /* wipe out trailing garbage */
-       while (p != end)
-               *p++ = '\0';
+       tape->error_in_pipeline_stage=0;
+
+       /*
+        *      On the next backup, perform the feedback loop again.
+        *      (I don't want to keep sense information between backups,
+        *       as some systems are constantly on, and the system load
+        *       can be totally different on the next backup).
+        */
+
+#if IDETAPE_PIPELINE
+       tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
+#else
+       tape->max_number_of_stages=0;
+#endif /* IDETAPE_PIPELINE */
+
+#if IDETAPE_DEBUG
+       if (tape->first_stage != NULL || tape->last_stage != NULL || tape->current_number_of_stages != 0) {
+               printk ("ide-tape: ide-tape pipeline bug\n");           
+       }
+#endif /* IDETAPE_DEBUG */
 }
 
+
 /*
  *     idetape_zero_packet_command just zeros a packet command and
  *     sets the number of retries to 0, as we haven't retried it yet.
@@ -2722,28 +3030,48 @@ struct request *idetape_next_rq_storage (ide_drive_t *drive)
 /*
  *     Block device interface functions
  *
- *     The default action is not to allow direct access to the block device
- *     interface (-EBUSY will be returned on open).
+ *     The block device interface should not be used for data transfers.
+ *     However, we still allow opening it so that we can issue general
+ *     ide driver configuration ioctl's, such as the interrupt unmask feature.
  */
 
 int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 
 {
-#if IDETAPE_ALLOW_OPENING_BLOCK_DEVICE
+       idetape_tape_t *tape=&(drive->tape);
+       unsigned long flags;
+                       
+       save_flags (flags);cli();
+
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_blkdev_open\n");
+#endif /* IDETAPE_DEBUG */
+
+       if (tape->busy) {
+               restore_flags (flags);          /* Allowing access only through one */
+               return (-EBUSY);                /* one file descriptor */
+       }
+
+       tape->busy=1;
+       restore_flags (flags);
+
        return (0);
-#else
-       printk ("ide-tape: The block device interface should not be used.\n");
-       printk ("ide-tape: Use the character device interfaces\n");
-       printk ("ide-tape: /dev/ht0 and /dev/nht0 instead.\n");
-       printk ("ide-tape: (Run linux/drivers/block/MAKEDEV.ide to create them)\n");
-       printk ("ide-tape: Refusing open request.\n");
-       return (-EBUSY);
-#endif /* IDETAPE_ALLOW_OPENING_BLOCK_DEVICE */
 }
 
 void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 
 {
+       idetape_tape_t *tape=&(drive->tape);
+       unsigned long flags;
+                       
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_blkdev_release\n");
+#endif /* IDETAPE_DEBUG */
+
+       save_flags (flags);cli();
+       tape->busy=0;
+       restore_flags (flags);
+
        return;
 }
 
@@ -2776,7 +3104,7 @@ int idetape_chrdev_lseek (struct inode *inode, struct file *file, off_t offset,
 /*
  *     Our character device read / write functions.
  *
- *     The tape is optimized to maximize throughpot when it is transfering
+ *     The tape is optimized to maximize throughput when it is transfering
  *     an integral number of the "continous transfer limit", which is
  *     a parameter of the specific tape (26 KB on my particular tape). The
  *     resulting increase in performance should be dramatical. In the
@@ -2872,9 +3200,8 @@ int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char
        if (count==0)
                return (0);
 
-
-       blocks=count/512;
-       remainder=count%512;
+       blocks=count/tape->tape_block_size;
+       remainder=count%tape->tape_block_size;
        if (remainder) {
 #if IDETAPE_DEBUG
        printk ("ide-tape: Padding read to block boundary\n");
@@ -2888,7 +3215,7 @@ int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char
        retval=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,blocks,tape->data_buffer);
        if (retval) {
                printk ("ide-tape: Error occured while reading\n");
-               actually_read=512*(tape->block_address-previous_block_address);
+               actually_read=tape->tape_block_size*(tape->block_address-previous_block_address);
                if (actually_read > count)
                        actually_read=count;
                if (actually_read != 0)
@@ -2907,7 +3234,7 @@ int idetape_chrdev_write (struct inode *inode, struct file *file, const char *bu
 {
        ide_drive_t *drive;
        idetape_tape_t *tape;
-       int blocks,remainder,retval,ctl_bytes;
+       int blocks,remainder,retval;
        const char *buf_ptr;
        unsigned long previous_block_address,actually_written;
 
@@ -2917,6 +3244,7 @@ int idetape_chrdev_write (struct inode *inode, struct file *file, const char *bu
 
        drive=idetape_chrdev.drive;
        tape=&(drive->tape);
+
        tape->last_dt_was_write=1;
 
        if (count==0)
@@ -2924,26 +3252,25 @@ int idetape_chrdev_write (struct inode *inode, struct file *file, const char *bu
 
        actually_written=0;
        buf_ptr=buf;
-       ctl_bytes=tape->capabilities.ctl*tape->tape_block_size;
-       blocks=count/ctl_bytes;
-       remainder=count%ctl_bytes;
+       blocks=count/tape->data_buffer_size;
+       remainder=count%tape->data_buffer_size;
 
        while (blocks) {
-#if IDETAPE_DEBUG
-               printk ("Copying %d bytes from the user space memory\n",ctl_bytes);
-#endif /* IDETAPE_DEBUG */
-               memcpy_fromfs (tape->data_buffer,buf_ptr,ctl_bytes);
-               buf_ptr+=ctl_bytes;
-#if IDETAPE_DEBUG
-               printk ("Adding a WRITE request to the block device request queue\n");
-#endif /* IDETAPE_DEBUG */
+               memcpy_fromfs (tape->temp_data_buffer,buf_ptr,tape->data_buffer_size);
+               buf_ptr+=tape->data_buffer_size;
                previous_block_address=tape->block_address;
-               retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,tape->capabilities.ctl,tape->data_buffer);
-               actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address);
+               retval=idetape_add_chrdev_write_request (drive,IDETAPE_WRITE_REQUEST,tape->capabilities.ctl,tape->temp_data_buffer);
+               if (tape->max_number_of_stages)
+                       actually_written+=tape->data_buffer_size;       /* Pipelined mode - Cheat :-) */
+               else
+                       actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address);
 
                if (retval) {
                        printk ("ide-tape: Error occured while writing\n");
-                       return (actually_written);
+                       if (tape->max_number_of_stages)
+                               return (0);
+                       else
+                               return (actually_written);
                }
                blocks--;
        }
@@ -2969,20 +3296,20 @@ int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, cons
        drive=idetape_chrdev.drive;
        tape=&(drive->tape);
 
-       blocks=count/512;
-       remainder=count%512;
+       blocks=count/tape->tape_block_size;
+       remainder=count%tape->tape_block_size;
        if (remainder)
                blocks++;
 #if IDETAPE_DEBUG
        printk ("Copying %d bytes from the user space memory\n",count);
 #endif /* IDETAPE_DEBUG */
 
-       memcpy_fromfs (tape->data_buffer,buf,count);
+       memcpy_fromfs (tape->temp_data_buffer,buf,count);
        if (remainder) {
 #if IDETAPE_DEBUG
        printk ("ide-tape: Padding written data to block boundary\n");
 #endif /* IDETAPE_DEBUG */
-               ptr=tape->data_buffer+(blocks-1)*512;
+               ptr=tape->temp_data_buffer+(blocks-1)*tape->tape_block_size;
                memset (ptr,0,remainder);
        }
 #if IDETAPE_DEBUG
@@ -2990,10 +3317,13 @@ int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, cons
 #endif /* IDETAPE_DEBUG */
 
        previous_block_address=tape->block_address;
-       retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,blocks,tape->data_buffer);
+       retval=idetape_add_chrdev_write_request (drive,IDETAPE_WRITE_REQUEST,blocks,tape->temp_data_buffer);
        if (retval) {
                printk ("ide-tape: Error occured while writing\n");
-               actually_written=512*(tape->block_address-previous_block_address);
+               if (tape->max_number_of_stages)
+                       actually_written=0;
+               else
+                       actually_written=tape->tape_block_size*(tape->block_address-previous_block_address);
                if (actually_written > count)
                        actually_written=count;
                return (actually_written);
@@ -3164,9 +3494,8 @@ int idetape_chrdev_open (struct inode *inode, struct file *filp)
        idetape_tape_t *tape;
        unsigned long flags;
        unsigned int minor;
-               
-       save_flags (flags);
-       cli();
+                       
+       save_flags (flags);cli();
 
 #if IDETAPE_DEBUG
        printk ("Reached idetape_chrdev_open\n");
@@ -3199,7 +3528,7 @@ int idetape_chrdev_open (struct inode *inode, struct file *filp)
        }
 
        tape->last_dt_was_write=0;
-       
+
        return (0);
 }
 
@@ -3225,6 +3554,8 @@ void idetape_chrdev_release (struct inode *inode, struct file *filp)
        tape=&(drive->tape);
        minor=MINOR (inode->i_rdev);
 
+       idetape_empty_pipeline (drive);
+
        if (tape->last_dt_was_write) {
                idetape_create_write_filemark_cmd (&pc,1);      /* Write a filemark */
                if (idetape_queue_pc_tail (drive,&pc)) {
@@ -3247,11 +3578,10 @@ void idetape_chrdev_release (struct inode *inode, struct file *filp)
                }
        }
 
-       save_flags (flags);
-       cli();
+       save_flags (flags);cli();
        tape->busy=0;
        restore_flags (flags);
-               
+
        return;
 }
 
@@ -3311,3 +3641,314 @@ int idetape_rewind_tape (ide_drive_t *drive)
        pc.current_position=pc.temp_buffer;
        return (idetape_queue_pc_tail (drive,&pc));
 }
+
+/*
+ *     Pipeline related functions
+ */
+
+/*
+ *     idetape_kmalloc_stage uses kmalloc to allocate a pipeline stage,
+ *     along with all the necessary small buffers which together make
+ *     a buffer of size tape->data_buffer_size or a bit more, in case
+ *     it is not a multiply of IDETAPE_ALLOCATION_BLOCK (it isn't ...).
+ *
+ *     Returns a pointer to the new allocated stage, or NULL if we
+ *     can't (or don't want to, in case we already have too many stages)
+ *     allocate a stage.
+ *
+ *     Pipeline stages are optional and are used to increase performance.
+ *     If we can't allocate them, we'll manage without them.
+ */
+idetape_pipeline_stage_t *idetape_kmalloc_stage (ide_drive_t *drive)
+
+{
+       idetape_tape_t *tape=&(drive->tape);
+       idetape_pipeline_stage_t *new_stage;
+       idetape_buffer_head_t *prev_bh,*bh;
+       int buffers_num,i;
+       
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_kmalloc_stage\n");
+#endif /* IDETAPE_DEBUG */
+
+       if (tape->current_number_of_stages==tape->max_number_of_stages) {
+               tape->pipeline_was_full_once=1;
+               return (NULL);
+       }
+               
+       new_stage=(idetape_pipeline_stage_t *) kmalloc (sizeof (idetape_pipeline_stage_t),GFP_KERNEL);
+       if (new_stage==NULL)
+               return (NULL);
+               
+       new_stage->next=new_stage->prev=NULL;
+
+       buffers_num=tape->data_buffer_size / IDETAPE_ALLOCATION_BLOCK;
+       if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
+               buffers_num++;
+
+       prev_bh=new_stage->bh=(idetape_buffer_head_t *) kmalloc (sizeof (idetape_buffer_head_t),GFP_KERNEL);
+       if (new_stage->bh==NULL) {
+               idetape_kfree_stage (new_stage);
+               return (NULL);
+       }
+       new_stage->bh->next=NULL;
+
+       new_stage->bh->data=kmalloc (IDETAPE_ALLOCATION_BLOCK,GFP_KERNEL);
+       if (new_stage->bh->data==NULL) {
+               idetape_kfree_stage (new_stage);
+               return (NULL);
+       }
+       
+       for (i=1;i<buffers_num;i++) {
+               bh=(idetape_buffer_head_t *) kmalloc (sizeof (idetape_buffer_head_t),GFP_KERNEL);
+               if (bh==NULL) {
+                       idetape_kfree_stage (new_stage);
+                       return (NULL);
+               }
+               bh->next=NULL;
+               prev_bh->next=bh;
+               bh->data=kmalloc (IDETAPE_ALLOCATION_BLOCK,GFP_KERNEL);
+               if (bh->data == NULL) {
+                       idetape_kfree_stage (new_stage);
+                       return (NULL);
+               }
+               prev_bh=bh;
+       }
+       return (new_stage);
+}
+
+/*
+ *     idetape_kfree_stage calls kfree to completly free a stage, along with
+ *     its related buffers.
+ */
+void idetape_kfree_stage (idetape_pipeline_stage_t *stage)
+
+{
+       idetape_buffer_head_t *prev_bh,*bh;
+       
+       if (stage == NULL)
+               return;
+
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_kfree_stage\n");
+#endif /* IDETAPE_DEBUG */
+       
+       bh=stage->bh;
+       
+       while (bh != NULL) {
+               prev_bh=bh;
+               if (bh->data != NULL)
+                       kfree (bh->data);
+               bh=bh->next;
+               kfree (prev_bh);
+       }
+       
+       kfree (stage);
+       return;
+}
+
+/*
+ *     idetape_copy_buffer_from_stage and idetape_copy_buffer_to_stage
+ *     copy data from/to the small buffers into/from a continous buffer.
+ */
+  
+void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer)
+
+{
+       idetape_buffer_head_t *bh;
+       char *ptr;
+
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_copy_buffer_from_stage\n");
+#endif /* IDETAPE_DEBUG */
+       
+       ptr=buffer;
+       bh=stage->bh;
+       
+       while (bh != NULL) {
+               memcpy (ptr,bh->data,IDETAPE_ALLOCATION_BLOCK);
+               bh=bh->next;
+               ptr=ptr+IDETAPE_ALLOCATION_BLOCK;
+       }
+       return;
+}
+
+/*
+ *     Here we copy a continuous data buffer to the various small buffers
+ *     in the pipeline stage.
+ */
+void idetape_copy_buffer_to_stage (idetape_pipeline_stage_t *stage,char *buffer)
+
+{
+       idetape_buffer_head_t *bh;
+       char *ptr;
+
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_copy_buffer_to_stage\n");
+#endif /* IDETAPE_DEBUG */
+
+       ptr=buffer;
+       bh=stage->bh;
+       
+       while (bh != NULL) {
+               memcpy (bh->data,ptr,IDETAPE_ALLOCATION_BLOCK);
+               bh=bh->next;
+               ptr=ptr+IDETAPE_ALLOCATION_BLOCK;
+       }
+       return;
+}
+
+/*
+ *     idetape_increase_max_pipeline_stages is a part of the feedback
+ *     loop which tries to find the optimum number of stages. In the
+ *     feedback loop, we are starting from a minimum maximum number of
+ *     stages, and if we sense that the pipeline is empty, we try to
+ *     increase it, until we reach the user compile time memory limit.
+ */
+
+void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
+
+{
+       idetape_tape_t *tape=&(drive->tape);
+       
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_increase_max_pipeline_stages\n");
+#endif /* IDETAPE_DEBUG */
+
+       if (!tape->pipeline_was_full_once)
+               return;
+
+       tape->max_number_of_stages+=IDETAPE_INCREASE_STAGES_RATE*
+                                       (IDETAPE_MAX_PIPELINE_STAGES-IDETAPE_MIN_PIPELINE_STAGES);
+
+       if (tape->max_number_of_stages >= IDETAPE_MAX_PIPELINE_STAGES)
+               tape->max_number_of_stages = IDETAPE_MAX_PIPELINE_STAGES;
+
+#if IDETAPE_DEBUG
+       printk ("Maximum number of stages: %d\n",tape->max_number_of_stages);
+#endif /* IDETAPE_DEBUG */
+
+       return;
+}
+
+/*
+ *     idetape_add_stage_tail adds a new stage at the end of the pipeline.
+ */
+void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage)
+
+{
+       idetape_tape_t *tape=&(drive->tape);
+       unsigned long flags;
+       
+#if IDETAPE_DEBUG
+               printk ("Reached idetape_add_stage_tail\n");
+#endif /* IDETAPE_DEBUG */
+
+       stage->next=NULL;
+       
+#if IDETAPE_DEBUG
+               printk ("Adding to the tail of the pipeline\n");
+#endif /* IDETAPE_DEBUG */
+
+       /*
+        *      Avoid a race condition - pipeline_locked is set whenever
+        *      we modify active_data_request from the lower level of
+        *      the driver. We wait until active_data_request is valid.
+        */
+        
+       while (tape->pipeline_locked);
+
+       save_flags (flags);cli ();
+       stage->prev=tape->last_stage;
+       if (tape->first_stage != NULL)
+               tape->last_stage->next=stage;
+       else
+               tape->first_stage=stage;
+       tape->last_stage=stage;
+       tape->current_number_of_stages++;
+
+       /*
+        *      Check if we are currently servicing requests in the bottom
+        *      part of the driver.
+        *
+        *      If not, wait for the pipeline to be full enough (75%) before
+        *      starting to service requests, so that we will be able to
+        *      keep up with the higher speeds of the tape.
+        */
+
+       if (tape->active_data_request == NULL &&
+               tape->current_number_of_stages >= 0.75*tape->max_number_of_stages) {
+               
+               restore_flags (flags);
+               idetape_insert_pipeline_into_queue (drive);             
+       }
+       else
+               restore_flags (flags);
+}
+
+/*
+ *     idetape_insert_pipeline_into_queue is used to start servicing the
+ *     pipeline stages.
+ */
+void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
+
+{
+       idetape_tape_t *tape=&(drive->tape);
+
+       if (tape->first_stage == NULL)
+               return;
+
+       if (tape->active_data_request == NULL) {
+               idetape_active_next_stage (drive);
+#if IDETAPE_DEBUG
+               printk ("Using ide_end\n");
+#endif /* IDETAPE_DEBUG */
+               (void) (ide_do_drive_cmd (drive,tape->active_data_request,ide_end));
+               return;
+       }
+}
+
+/*
+ *     idetape_active_next_stage will "move the pipeline" one stage -
+ *     Inserting the first stage into the "active place", and using kfree
+ *     to free the stage.
+ */
+void idetape_active_next_stage (ide_drive_t *drive)
+
+{
+       idetape_tape_t *tape=&(drive->tape);
+       idetape_pipeline_stage_t *stage;
+       struct request *rq;
+       unsigned long flags;
+
+#if IDETAPE_DEBUG
+       printk ("Reached idetape_active_next_stage\n");
+       if (tape->first_stage == NULL) {
+               printk ("ide-tape: ide-tape.c bug - tape->first_stage is NULL\n");
+               return;
+       }
+#endif /* IDETAPE_DEBUG */
+       
+       stage=tape->first_stage;
+
+       idetape_copy_buffer_from_stage (stage,tape->data_buffer);
+       rq=idetape_next_rq_storage (drive);
+       *rq=stage->rq;
+       rq->buffer=tape->data_buffer;
+
+       save_flags (flags);cli ();
+       tape->first_stage=stage->next;
+       if (tape->first_stage == NULL)
+               tape->last_stage=NULL;
+       tape->current_number_of_stages--;
+       tape->active_data_request=rq;
+       restore_flags (flags);
+       
+       idetape_kfree_stage (stage);
+}
index 7dabd4e1a4601bca5a9c5a0e2209ffd6367afa0c..c88a4d81481a666b10629762fc34821335ca0513 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.h      Version 1.0 - ALPHA     Dec  3, 1995
+ * linux/drivers/block/ide-tape.h      Version 1.1 - ALPHA     Dec  14, 1995
  *
  * Copyright (C) 1995 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  */
 
 /**************************** Tunable parameters *****************************/
 
+/*
+ *     This is probably the most important configuration option.
+ *
+ *     Pipelined operation mode has the potential to maximize the
+ *     performance of the driver and thus to saturate the throughput
+ *     to the maximum value supported by the tape. Currently, pipelined
+ *     mode is supported only on writes.
+ *
+ *     In pipelined mode we are servicing requests without blocking the
+ *     user backup program. For example, on a write request, we will add it
+ *     to the pipeline and return without waiting for it to complete. The
+ *     user program will then have enough time to prepare the next blocks
+ *     while the tape is still busy working on the previous requests.
+ *
+ *     Pipelined (write) operation mode is enabled by default, but since
+ *     it has a few downfalls as well (Use of additional memory and deferred
+ *      error code to the application), you may wish to disable it.
+ *     Further explanation of pipelined mode is available in ide-tape.c .
+ */
+
+#define        IDETAPE_PIPELINE        1
+
+/*
+ *     Pipelined mode parameters.
+ *
+ *     We try to use the minimum number of stages which is enough to
+ *     keep the tape constantly streaming. To accomplish that, we implement
+ *     a feedback loop around the maximum number of stages:
+ *
+ *     We start from MIN maximum stages (we will not even use MIN stages
+ *      if we don't need them), increment it by RATE*(MAX-MIN)
+ *     whenever we sense that the pipeline is empty, until we reach
+ *     the optimum value or until we reach MAX.
+ */
+#define        IDETAPE_MIN_PIPELINE_STAGES             100
+#define        IDETAPE_MAX_PIPELINE_STAGES             200
+#define        IDETAPE_INCREASE_STAGES_RATE            0.2
+
+/*
+ *     It seems that dynamically allocating buffers of about 32KB
+ *     each is doomed to fail, unless we are in or very near the
+ *     initialization stage. Take care when changing this value, as it
+ *     is now optimized with the design of kmalloc, so that we will not
+ *     allocate parts of a page. Setting the size to 512 bytes, for example,
+ *     would cause kmalloc to allocate for us 1024 bytes, and to
+ *     unnecessarily waste double amount of memory.
+ */
+
+#if PAGE_SIZE == 4096
+       #define IDETAPE_ALLOCATION_BLOCK                500
+#elif PAGE_SIZE == 8192
+       #define IDETAPE_ALLOCATION_BLOCK                496
+#else /* ??? Not defined by linux/mm/kmalloc.c */
+       #define IDETAPE_ALLOCATION_BLOCK                512
+#endif
+
 /*
  *     Setting IDETAPE_DEBUG to 1 will:
  *
 
 #define        IDETAPE_MAX_PC_RETRIES  2
 
-/*
- *     In case the tape is not at the requested block, we re-position the
- *     tape. Repeat the procedure for IDETAPE_LOCATE_RETRIES times before
- *     we give up and abort the request. Note that this should not usually
- *     happen when using only the character device interface.
- */
-
-#define        IDETAPE_LOCATE_RETRIES  1
-
 /*
  *     With each packet command, we allocate a buffer of
  *     IDETAPE_TEMP_BUFFER_SIZE bytes. This is used for several packet
  *     the handling of a specific request.
  *
  *     Follows a worse case calculation of the required storage, with a
- *     large safety margin. Hopefully. :-)
+ *     large safety margin.
  */
 
-#define        IDETAPE_PC_STACK        10+\
-                               IDETAPE_MAX_PC_RETRIES+\
-                               3*IDETAPE_LOCATE_RETRIES*IDETAPE_MAX_PC_RETRIES
+#define        IDETAPE_PC_STACK        20+IDETAPE_MAX_PC_RETRIES
+
 /*
- *     Media access packet command (like the LOCATE command) have immediate
- *     status with a delayed (and usually long) execution. The tape doesn't
- *     issue an interrupt when the command is actually complete (so that the
- *     bus is freed to use the other IDE device on the same interface), so we
- *     must for poll for this event.
+ *     DSC polling parameters.
+ *
+ *     Polling for DSC (a single bit in the status register) is a very
+ *     important function in ide-tape. There are two cases in which we
+ *     poll for DSC:
+ *
+ *     1.      Before a read/write packet command, to ensure that we
+ *             can transfer data from/to the tape's data buffers, without
+ *             causing an actual media access. In case the tape is not
+ *             ready yet, we take out our request from the device
+ *             request queue, so that ide.c will service requests from
+ *             the other device on the same interface meanwhile.
  *
- *     We set a timer with polling frequency of 1/IDETAPE_DSC_MEDIA_ACCESS_FREQUENCY
- *     in this case. We also poll for DSC *before* read/write commands. At
- *     this time the DSC role is changed and instead of signalling command
- *     completion, it will signal buffer availability. Since read/write
- *     commands are fast in comparision to media access commands, the polling
- *     frequency here should be much higher.
+ *             The polling frequency is 1/IDETAPE_DSC_READ_WRITE_FREQUENCY,
+ *             and it should be relatively fast. The default is a period
+ *             of 50 msec.
  *
- *     We will insist of reading DSC=1 for IDETAPE_DSC_COUNT times in a row,
- *     to accommodate for random fluctuations in the sampling of DSC.
- *     We will also set IDETAPE_DSC_POLLING_FREQUENCY to a rather low
- *     frequency which besides freeing the CPU and the bus will let
- *     random fluctuations a time to settle down.
+ *     2.      After the successful initialization of a "media access
+ *             packet command", which is a command which can take a long
+ *             time to complete (it can be several seconds or even an hour).
  *
+ *             Again, we postpone our request in the middle to free the bus
+ *             for the other device. The polling frequency here should be
+ *             lower than the read/write frequency since those media access
+ *             commands are slow. We start from a "fast" frequency -
+ *             IDETAPE_DSC_FAST_MEDIA_ACCESS_FREQUENCY (one second), and
+ *             if we don't receive DSC after IDETAPE_FAST_SLOW_THRESHOLD
+ *             (5 minutes), we switch it to a lower frequency -
+ *             IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY (1 minute).
+ *             
  *     We also set a timeout for the timer, in case something goes wrong.
  *     The timeout should be longer then the maximum execution time of a
  *     tape operation. I still have to measure exactly how much time does
  *     it take to space over a far filemark, etc. It seemed that 15 minutes
  *     was way too low, so I am meanwhile setting it to a rather large
- *     timeout - 2 Hours.
+ *     timeout - 2 Hours ...
  *
- *     Once we pass a threshold, the polling frequency will change to
- *     a slow frequency: On relatively fast operations, there is a point
- *     in polling fast, but if we sense that the operation is taking too
- *     much time, we will poll at a lower frequency.
  */
 
+#define        IDETAPE_DSC_READ_WRITE_FREQUENCY        5*HZ/100        /* 50 msec */
 #define        IDETAPE_DSC_FAST_MEDIA_ACCESS_FREQUENCY 1*HZ            /* 1 second */
 #define        IDETAPE_FAST_SLOW_THRESHOLD             5*60*HZ         /* 5 minutes */
 #define IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY        60*HZ           /* 1 minute */
-#define        IDETAPE_DSC_READ_WRITE_FREQUENCY        HZ/20           /* 50 msec */
 #define        IDETAPE_DSC_TIMEOUT                     2*60*60*HZ      /* 2 hours */
-#define IDETAPE_DSC_COUNT                      1               /* Assume no DSC fluctuations */
-
-/*
- *     As explained in many places through the code, we provide both a block
- *     device and a character device interface to the tape. The block device
- *     interface is needed for compatibility with ide.c. The character device
- *     interface is the higher level of the driver, and passes requests
- *     to the lower part of the driver which interfaces with ide.c.
- *     Using the block device interface, we can bypass this high level
- *     of the driver, talking directly with the lower level part.
- *
- *     It is intended that the character device interface will be used by
- *     the user. To prevent mistakes in this regard, opening of the block
- *     device interface will be refused if ALLOW_OPENING_BLOCK_DEVICE is 0.
- *
- *     Do not change the following parameter unless you are developing
- *     the driver itself.
- */
-#define IDETAPE_ALLOW_OPENING_BLOCK_DEVICE     0
 
 /*************************** End of tunable parameters ***********************/
 
@@ -225,6 +259,30 @@ typedef struct {
        byte reserved19;
 } idetape_capabilities_page_t;
 
+/*
+ *     A pipeline stage contains several small buffers of type
+ *     idetape_buffer_head_t. This is necessary since dynamical allocation
+ *     of large (32 KB or so) continuous memory blocks will usually fail.
+ */
+typedef struct idetape_buffer_head_s {
+       char *data;                                     /* Pointer to data (512 bytes by default) */
+       struct idetape_buffer_head_s *next;
+} idetape_buffer_head_t;
+
+/*
+ *     A pipeline stage.
+ *
+ *     In a pipeline stage we have a request, pointer to a list of small
+ *     buffers, and pointers to the near stages.
+ */
+
+typedef struct idetape_pipeline_stage_s {
+       struct request rq;                              /* The correspoding request */
+       idetape_buffer_head_t *bh;                      /* The data buffers */
+       struct idetape_pipeline_stage_s *next,*prev;    /* Pointers to the next and previous stages */
+} idetape_pipeline_stage_t;
+
 /*
  *     Most of our global data which we need to save even as we leave the
  *     driver due to an interrupt or a timer event is stored in a variable
@@ -268,9 +326,9 @@ typedef struct {
         *      another ide block device which receives requests and completes
         *      them.
         *
-        *      However, our requests usually don't originate in the buffer
-        *      cache but rather in ide-tape.c itself. Here we provide safe
-        *      storage for such requests.
+        *      However, our requests don't originate in the buffer cache but
+        *      rather in ide-tape.c itself. Here we provide safe storage for
+        *      such requests.
         */
 
        struct request rq_stack [IDETAPE_PC_STACK];
@@ -279,31 +337,37 @@ typedef struct {
        /*
         *      While polling for DSC we use postponed_rq to postpone the
         *      current request so that ide.c will be able to service
-        *      pending requests on the other device.
+        *      pending requests on the other device. Note that at most
+        *      we will have only one DSC (usually data transfer) request
+        *      in the device request queue. Additional request can be
+        *      queued in our internal pipeline, but they will be visible
+        *      to ide.c only one at a time.
         */
 
        struct request *postponed_rq;
-       byte dsc_count;         
-       unsigned long dsc_polling_start;
+       
+       /*
+        *      DSC polling variables.
+        */
+        
+       byte dsc_count;                         /* We received DSC dsc_count times in a row */
+       unsigned long dsc_polling_start;        /* The time in which we started polling for DSC */
        struct timer_list dsc_timer;            /* Timer used to poll for dsc */
-       unsigned long dsc_polling_frequency;
+       unsigned long dsc_polling_frequency;    /* The current polling frequency */
        unsigned long dsc_timeout;              /* Maximum waiting time */
-       byte dsc_received;
+       byte dsc_received;                      /* Set when we receive DSC */
 
+       byte request_status;
+       byte request_dsc_callback;
+       byte last_status;                       /* Contents of the tape status register */
+                                               /* before the current request (saved for us */
+                                               /* by ide.c) */
        /* Position information */
        
        byte partition_num;                     /* Currently not used */
        unsigned long block_address;            /* Current block */
        byte block_address_valid;               /* 0 When the tape position is unknown */
                                                /* (To the tape or to us) */
-       unsigned long locate_to;                /* We want to reach this block, as a part */
-                                               /* of handling the current request */
-       byte locate_retries;                    /* Each time, increase locate_retries */
-
-       unsigned long last_written_block;       /* Once writing started, we don't allow read */
-       byte last_written_valid;                /* access beyond the last written block */
-                                               /* ??? Should I remove this ? */
-
        /* Last error information */
        
        byte sense_key,asc,ascq;
@@ -311,17 +375,60 @@ typedef struct {
        /* Character device operation */
 
        unsigned char last_dt_was_write;        /* Last character device data transfer was a write */
-       byte busy;                              /* Device already opened */     
+       byte busy;                              /* Device already opened */
 
        /* Device information */
        
-       unsigned short tape_block_size;
-       idetape_capabilities_page_t capabilities;       /* Capabilities and Mechanical Page */
+       unsigned short tape_block_size;                 /* Usually 512 or 1024 bytes */
+       idetape_capabilities_page_t capabilities;       /* Copy of the tape's Capabilities and Mechanical Page */
 
-       /* Data buffer */
+       /*
+        *      Active data transfer request parameters.
+        *
+        *      At most, there is only one ide-tape originated data transfer
+        *      request in the device request queue. This allows ide.c to
+        *      easily service requests from the other device when we
+        *      postpone our active request. In the pipelined operation
+        *      mode, we use our internal pipeline structure to hold
+        *      more data requests.
+        *
+        *      The data buffer size is chosen based on the tape's
+        *      recommendation.
+        */
        
-       char *data_buffer;
+       struct request *active_data_request;    /* Pointer to the request which is waiting in the device request queue */
+       char *data_buffer;                      /* The correspoding data buffer (for read/write requests) */
+       int data_buffer_size;                   /* Data buffer size (chosen based on the tape's recommendation */
+       char *temp_data_buffer;                 /* Temporary buffer for user <-> kernel space data transfer */
 
+       /*
+        *      Pipeline parameters.
+        *
+        *      To accomplish non-pipelined mode, we simply set the following
+        *      variables to zero (or NULL, where appropriate).
+        */
+               
+       int current_number_of_stages;           /* Number of currently used stages */
+       int max_number_of_stages;               /* We will not allocate more than this number of stages */
+       idetape_pipeline_stage_t *first_stage;  /* Will be serviced after the currently active request */
+       idetape_pipeline_stage_t *last_stage;   /* New write requests will be added to the pipeline here */
+       int pipeline_was_full_once;             /* Set at the first time we fill the pipeline since the tape was opened */
+       int error_in_pipeline_stage;            /* Set when an error was detected in one of the pipeline stages */      
+       int pipeline_locked;                    /* Against race conditions ... */
+       
 } idetape_tape_t;
 
+#define POLL_HWIF_TAPE_DRIVE                                                   \
+       if (hwif->tape_drive != NULL) {                                         \
+               if (hwif->tape_drive->tape.request_status) {                    \
+                       OUT_BYTE(hwif->tape_drive->select.all,IDE_SELECT_REG);  \
+                       hwif->tape_drive->tape.last_status=GET_STAT();          \
+                       hwif->tape_drive->tape.request_status=0;                \
+               }                                                               \
+               if (hwif->tape_drive->tape.request_dsc_callback) {              \
+                       hwif->tape_drive->tape.request_dsc_callback=0;          \
+                       idetape_put_back_postponed_request(hwif->tape_drive);   \
+               }                                                               \
+       }
+
 #endif /* IDETAPE_H */
index 3e89315adafe99bece863b50fbf8351cfae5ed57..5a6ab6cc28dfbae16be9199e4bd3e804176c4895 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c  Version 5.22  Dec 10, 1995
+ *  linux/drivers/block/ide.c  Version 5.23  Dec 15, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
  *                     generalized ide_do_drive_cmd() for tape/cdrom driver use
  *  Version 5.21       fix nasty cdrom/tape bug (ide_preempt was messed up)
  *  Version 5.22       fix ide_xlate_1024() to work with/without drive->id
+ *  Version 5.23       miscellaneous touch-ups
  *
  *  Driver compile-time options are in ide.h
  *
  *     - add ioctls to get/set interface timings on various interfaces
  *     - add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
  *     - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
+ *     - add new HT6560B code from malafoss@snakemail.hut.fi
  */
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
@@ -315,7 +317,9 @@ static void init_ide_data (void)
                hwif->name[1]   = 'd';
                hwif->name[2]   = 'e';
                hwif->name[3]   = '0' + h;
-
+#ifdef CONFIG_BLK_DEV_IDETAPE
+               hwif->tape_drive = NULL;
+#endif /* CONFIG_BLK_DEV_IDETAPE */
                for (unit = 0; unit < MAX_DRIVES; ++unit) {
                        ide_drive_t *drive = &hwif->drives[unit];
 
@@ -415,6 +419,7 @@ void ide_hwif_select (ide_hwif_t *hwif)
        static byte current_select = 0;
 
        if (hwif->select != current_select) {
+               byte t;
                unsigned long flags;
                save_flags (flags);
                cli();
@@ -422,8 +427,16 @@ void ide_hwif_select (ide_hwif_t *hwif)
                (void) inb(0x3e6);
                (void) inb(0x3e6);
                (void) inb(0x3e6);
-               (void) inb(0x3e6);
-               outb(current_select,0x3e6);
+               /*
+                * Avoid clobbering existing bits at 0x3e6:
+                *      bit5 (0x20) - disables fast interface speed
+                *      bit0 (0x01) - enables secondary interface
+                *      we don't touch any other bits
+                */
+               t = inb(0x3e6);
+               t &= (~0x21);
+               t |= (current_select & 0x21);
+               outb(t,0x3e6);
                restore_flags (flags);
        }
 }
@@ -877,7 +890,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
        } else {
                if (drive->media == ide_disk && (stat & ERR_STAT)) {
                        /* err has different meaning on cdrom and tape */
-                       if (err & BBD_ERR)              /* retries won't help this! */
+                       if (err & (BBD_ERR | ECC_ERR))  /* retries won't help these */
                                rq->errors = ERROR_MAX;
                        else if (err & TRK0_ERR)        /* help it find track zero */
                                rq->errors |= ERROR_RECAL;
@@ -1271,8 +1284,10 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
        if (rq->cmd == IDE_DRIVE_CMD) {
                byte *args = rq->buffer;
                if (args) {
+#ifdef DEBUG
                        printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n",
                         drive->name, args[0], args[1], args[2]);
+#endif
                        OUT_BYTE(args[2],io_base+IDE_FEATURE_OFFSET);
                        ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
                        return;
@@ -1341,11 +1356,17 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq)
        if (hwif->select)
                ide_hwif_select (hwif);
 #endif
+
+#ifdef CONFIG_BLK_DEV_IDETAPE
+       POLL_HWIF_TAPE_DRIVE;   /* macro from ide-tape.h */
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+
        OUT_BYTE(drive->select.all,IDE_SELECT_REG);
        if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
                printk("%s: drive not ready for command\n", drive->name);
                return;
        }
+       
        if (!drive->special.all) {
 #ifdef CONFIG_BLK_DEV_IDEATAPI
                switch (drive->media) {
@@ -1638,6 +1659,12 @@ void ide_init_drive_cmd (struct request *rq)
  * returns without waiting for the new rq to be completed.  As above,
  * This is VERY DANGEROUS, and is intended for careful use by the
  * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c,
+ * when operating in the pipelined operation mode).
  */
 int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
 {
@@ -1664,7 +1691,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
                if (action != ide_preempt)
                        bdev->request_fn();
        } else {
-               if (action == ide_wait) {
+               if (action == ide_wait || action == ide_end) {
                        while (cur_rq->next != NULL)    /* find end of list */
                                cur_rq = cur_rq->next;
                }
@@ -1704,7 +1731,12 @@ static int ide_open(struct inode * inode, struct file * filp)
                check_disk_change(inode->i_rdev);
                ide_init_drive_cmd (&rq);
                rq.buffer = door_lock;
-               return ide_do_drive_cmd(drive, &rq, ide_wait);
+               /*
+                * Ignore the return code from door_lock,
+                * since the open() has already succeeded,
+                * and the door_lock is irrelevant at this point.
+                */
+               (void) ide_do_drive_cmd(drive, &rq, ide_wait);
        }
        return 0;
 }
@@ -1997,7 +2029,7 @@ static int ide_check_media_change (kdev_t i_rdev)
        return 0;
 }
 
-static void fixstring (byte *s, const int bytecount, const int byteswap)
+void ide_fixstring (byte *s, const int bytecount, const int byteswap)
 {
        byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
 
@@ -2055,9 +2087,9 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
                 || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
                        bswap = 0;      /* Vertos drives may still be weird */
        }
-       fixstring (id->model,     sizeof(id->model),     bswap);
-       fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
-       fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+       ide_fixstring (id->model,     sizeof(id->model),     bswap);
+       ide_fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
+       ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
 
        /*
         * Check for an ATAPI device
@@ -2678,15 +2710,19 @@ void ide_setup (char *s)
                                /*
                                 * Using 0x1c and 0x1d apparently selects a
                                 * faster interface speed than 0x3c and 0x3d.
+                                * (bit5 (0x20) selects fast speed when set)
+                                * (bit0 (0x01) selects second interface)
                                 *
-                                * Need to add an ioctl to select between them.
+                                * Need to set these per-drive, rather than
+                                * per-hwif, and also add an ioctl to select
+                                * between them.
                                 */
                                if (check_region(0x3e6,1)) {
                                        printk(" -- HT6560 PORT 0x3e6 ALREADY IN USE");
                                        goto done;
                                }
                                request_region(0x3e6, 1, hwif->name);
-                               ide_hwifs[0].select = 0x3c;
+                               ide_hwifs[0].select = 0x1c;
                                ide_hwifs[1].select = 0x3d;
                                goto do_serialize;
 #endif /* SUPPORT_HT6560B */
@@ -2741,13 +2777,13 @@ int ide_xlate_1024 (kdev_t i_rdev, int offset, const char *msg)
                return 0;
 
        if (drive->id) {
-               drive->bios_cyl  = drive->id->cyls;
-               drive->bios_head = drive->id->heads;
-               drive->bios_sect = drive->id->sectors;
+               drive->cyl  = drive->id->cyls;
+               drive->head = drive->id->heads;
+               drive->sect = drive->id->sectors;
        }
-       drive->cyl  = drive->bios_cyl;
-       drive->head = drive->bios_head;
-       drive->sect = drive->bios_sect;
+       drive->bios_cyl  = drive->cyl;
+       drive->bios_head = drive->head;
+       drive->bios_sect = drive->sect;
        drive->special.b.set_geometry = 1;
 
        tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
index 00a0303ff164805726c27a25531b418b7f5c1eaa..5c96af6f521582e2e532f8749d708d1487062595 100644 (file)
@@ -355,6 +355,9 @@ typedef struct hwif_s {
        struct request request_sense_request;   /* from ide-cd.c */
        struct packet_command request_sense_pc; /* from ide-cd.c */
 #endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDETAPE
+       ide_drive_t     *tape_drive;    /* Pointer to the tape on this interface */
+#endif /* CONFIG_BLK_DEV_IDETAPE */
        } ide_hwif_t;
 
 /*
@@ -412,6 +415,14 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
  */
 void ide_error (ide_drive_t *drive, const char *msg, byte stat);
 
+/*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
+void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+
 /*
  * This routine busy-waits for the drive status to be not "busy".
  * It then checks the status for all of the "good" bits and none
@@ -443,7 +454,8 @@ void ide_init_drive_cmd (struct request *rq);
 typedef enum
        {ide_wait,      /* insert rq at end of list, and wait for it */
         ide_next,      /* insert rq immediately after current request */
-        ide_preempt}   /* insert rq in front of current request */
+        ide_preempt,   /* insert rq in front of current request */
+        ide_end}       /* insert rq at end of list, but don't wait for it */
  ide_action_t;
 
 /*
@@ -465,6 +477,12 @@ typedef enum
  * returns without waiting for the new rq to be completed.  As above,
  * This is VERY DANGEROUS, and is intended for careful use by the 
  * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c,
+ * when operating in the pipelined operation mode).
  */
 int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
  
@@ -535,6 +553,13 @@ void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t
  
 void idetape_register_chrdev (void);
 
+/*
+ *     The following function is called to re-insert a postponed tape
+ *     request into the request queue.
+ */
+void idetape_put_back_postponed_request (ide_drive_t *drive);
+
 #endif /* CONFIG_BLK_DEV_IDETAPE */
 
 #ifdef CONFIG_BLK_DEV_TRITON
index c43a7c70657b4d922185d94b75441c330774a0da..eaf3bf0a85efef982cb3ac4d67e7a55b5e5a02f0 100644 (file)
@@ -623,6 +623,7 @@ int blk_dev_init(void)
                req->next = NULL;
        }
        memset(ro_bits,0,sizeof(ro_bits));
+       rd_init();
 #ifdef CONFIG_BLK_DEV_IDE
        ide_init();             /* this MUST preceed hd_init */
 #endif
diff --git a/drivers/block/ramdisk.c b/drivers/block/ramdisk.c
deleted file mode 100644 (file)
index f4dbbd7..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *  linux/kernel/blk_drv/ramdisk.c
- *
- *  Written by Theodore Ts'o, 12/2/91
- *
- * Modifications by Fred N. van Kempen to allow for bootable root
- * disks (which are used in LINUX/Pro).  Also some cleanups.  03/03/93
- */
-
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-
-#define MAJOR_NR  MEM_MAJOR
-#include <linux/blk.h>
-
-#define RAMDISK_MINOR  1
-
-extern void wait_for_keypress(void);
-
-char   *rd_start;
-int    rd_length = 0;
-static int rd_blocksizes[2] = {0, 0};
-
-static void do_rd_request(void)
-{
-       int     len;
-       char    *addr;
-
-repeat:
-       INIT_REQUEST;
-       addr = rd_start + (CURRENT->sector << 9);
-       len = CURRENT->current_nr_sectors << 9;
-
-       if ((MINOR(CURRENT->rq_dev) != RAMDISK_MINOR) ||
-           (addr+len > rd_start+rd_length)) {
-               end_request(0);
-               goto repeat;
-       }
-       if (CURRENT-> cmd == WRITE) {
-               (void ) memcpy(addr,
-                             CURRENT->buffer,
-                             len);
-       } else if (CURRENT->cmd == READ) {
-               (void) memcpy(CURRENT->buffer, 
-                             addr,
-                             len);
-       } else
-               panic("RAMDISK: unknown RAM disk command !\n");
-       end_request(1);
-       goto repeat;
-}
-
-static struct file_operations rd_fops = {
-       NULL,                   /* lseek - default */
-       block_read,             /* read - general block-dev read */
-       block_write,            /* write - general block-dev write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* select */
-       NULL,                   /* ioctl */
-       NULL,                   /* mmap */
-       NULL,                   /* no special open code */
-       NULL,                   /* no special release code */
-       block_fsync             /* fsync */
-};
-
-/*
- * Returns amount of memory which needs to be reserved.
- */
-long rd_init(long mem_start, int length)
-{
-       int     i;
-       char    *cp;
-
-       if (register_blkdev(MEM_MAJOR,"rd",&rd_fops)) {
-               printk("RAMDISK: Unable to get major %d.\n", MEM_MAJOR);
-               return 0;
-       }
-       blk_dev[MEM_MAJOR].request_fn = DEVICE_REQUEST;
-       rd_start = (char *) mem_start;
-       rd_length = length;
-       cp = rd_start;
-       for (i=0; i < length; i++)
-               *cp++ = '\0';
-
-       for(i=0;i<2;i++) rd_blocksizes[i] = 1024;
-       blksize_size[MAJOR_NR] = rd_blocksizes;
-
-       return(length);
-}
-
-static void do_load(void)
-{
-       struct buffer_head *bh;
-       struct super_block {
-         union
-         {
-           char minix [sizeof (struct minix_super_block)];
-           char ext2 [sizeof (struct ext2_super_block)];
-         } record;
-       } sb;
-       struct minix_super_block *minixsb =
-               (struct minix_super_block *)&sb;
-       struct ext2_super_block *ext2sb =
-               (struct ext2_super_block *)&sb;
-       int             block, tries;
-       int             i = 1;
-       int             nblocks;
-       char            *cp;
-       
-       /*
-        * Check for a super block on the diskette.
-        * The old-style boot/root diskettes had their RAM image
-        * starting at block 512 of the boot diskette.  LINUX/Pro
-        * uses the entire diskette as a file system, so in that
-        * case, we have to look at block 0.  Be intelligent about
-        * this, and check both... - FvK
-        */
-       for (tries = 0; tries < 1000; tries += 512) {
-               block = tries;
-               bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0,  PAGE_SIZE);
-               if (!bh) {
-                       printk("RAMDISK: I/O error while looking for super block!\n");
-                       return;
-               }
-
-               /* This is silly- why do we require it to be a MINIX FS? */
-               *((struct super_block *) &sb) =
-                       *((struct super_block *) bh->b_data);
-               brelse(bh);
-
-
-               /* Try Minix */
-               nblocks = -1;
-               if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
-                   minixsb->s_magic == MINIX_SUPER_MAGIC2) {
-                       printk("RAMDISK: Minix filesystem found at block %d\n",
-                               block);
-                       nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
-               }
-
-               /* Try ext2 */
-               if (nblocks == -1 && ext2sb->s_magic == EXT2_SUPER_MAGIC)
-               {
-                       printk("RAMDISK: Ext2 filesystem found at block %d\n",
-                               block);
-                       nblocks = ext2sb->s_blocks_count;
-               }
-
-               if (nblocks == -1)
-               {
-                       printk("RAMDISK: trying old-style RAM image.\n");
-                       continue;
-               }
-
-               if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
-                       printk("RAMDISK: image too big! (%d/%d blocks)\n",
-                                       nblocks, rd_length >> BLOCK_SIZE_BITS);
-                       return;
-               }
-               printk("RAMDISK: Loading %d blocks into RAM disk", nblocks);
-
-               /* We found an image file system.  Load it into core! */
-               cp = rd_start;
-               while (nblocks) {
-                       if (nblocks > 2) 
-                               bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0,  PAGE_SIZE);
-                       else
-                               bh = bread(ROOT_DEV, block, BLOCK_SIZE);
-                       if (!bh) {
-                               printk("RAMDISK: I/O error on block %d, aborting!\n", 
-                               block);
-                               return;
-                       }
-                       (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
-                       brelse(bh);
-                       if (!(nblocks-- & 15)) printk(".");
-                       cp += BLOCK_SIZE;
-                       block++;
-                       i++;
-               }
-               printk("\ndone\n");
-
-               /* We loaded the file system image.  Prepare for mounting it. */
-               ROOT_DEV = MKDEV(MEM_MAJOR, RAMDISK_MINOR);
-               return;
-       }
-}
-
-/*
- * If the root device is the RAM disk, try to load it.
- * In order to do this, the root device is originally set to the
- * floppy, and we later change it to be RAM disk.
- */
-void rd_load(void)
-{
-       struct inode inode;
-       struct file filp;
-
-       /* If no RAM disk specified, give up early. */
-       if (!rd_length)
-               return;
-       printk("RAMDISK: %d bytes, starting at 0x%p\n",
-                       rd_length, rd_start);
-
-       /* If we are doing a diskette boot, we might have to pre-load it. */
-       if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR)
-               return;
-
-       /* for Slackware install disks */
-       printk(KERN_NOTICE "VFS: Insert root floppy to be loaded into ramdisk and press ENTER\n");
-       wait_for_keypress();
-
-       memset(&filp, 0, sizeof(filp));
-       memset(&inode, 0, sizeof(inode));
-       inode.i_rdev = ROOT_DEV;
-       filp.f_mode = 1; /* read only */
-       filp.f_inode = &inode;
-       if(blkdev_open(&inode, &filp) == 0 ){
-               do_load();
-               if(filp.f_op && filp.f_op->release)
-                       filp.f_op->release(&inode,&filp);
-       }
-}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
new file mode 100644 (file)
index 0000000..186a654
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * ramdisk.c - Multiple ramdisk driver - gzip-loading version - v. 0.8 beta.
+ * 
+ * (C) Chad Page, Theodore Ts'o, et. al, 1995. 
+ *
+ * This ramdisk is designed to have filesystems created on it and mounted
+ * just like a regular floppy disk.  
+ *  
+ * It also does something suggested by Linus: use the buffer cache as the
+ * ramdisk data.  This makes it possible to dynamically allocate the ramdisk
+ * buffer - with some consequences I have to deal with as I write this. 
+ * 
+ * This code is based on the original ramdisk.c, written mostly by
+ * Theodore Ts'o (TYT) in 1991.  The code was largely rewritten by
+ * Chad Page to use the buffer cache to store the ramdisk data in
+ * 1995; Theodore then took over the driver again, and cleaned it up
+ * for inclusion in the mainline kernel.
+ *
+ * The original CRAMDISK code was written by Richard Lyons, and
+ * adapted by Chad Page to use the new ramdisk interface.  Theodore
+ * Ts'o rewrote it so that both the compressed ramdisk loader and the
+ * kernel decompressor uses the same inflate.c codebase.  The ramdisk
+ * loader now also loads into a dynamic (buffer cache based) ramdisk,
+ * not the old static ramdisk.  Support for the old static ramdisk has
+ * been completely removed.
+ */
+
+#include <linux/sched.h>
+#include <linux/minix_fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+
+extern void wait_for_keypress(void);
+
+/*
+ * 35 has been officially registered as the RAMDISK major number, but
+ * so is the original MAJOR number of 1.  We're using 1 in
+ * include/linux/major.h for now
+ */
+#define MAJOR_NR RAMDISK_MAJOR
+#include <linux/blk.h>
+
+#define BUILD_CRAMDISK
+#define NUM_RAMDISKS 8
+
+void rd_load(void);
+static int crd_load(struct file *fp, struct file *outfp);
+
+/* Various static variables go here... mostly used within the ramdisk code only. */
+
+static int rd_length[NUM_RAMDISKS];
+static int rd_blocksizes[NUM_RAMDISKS];
+
+/*
+ * Parameters for the boot-loading of the ramdisk.  These are set by
+ * init/main.c (from arguments to the kernel command line) or from the
+ * architecture-specific setup routine (from the stored bootsector
+ * information). 
+ */
+int rd_doload = 0;             /* 1 = load ramdisk, 0 = don't load */
+int rd_prompt = 1;             /* 1 = prompt for ramdisk, 0 = don't prompt */
+int rd_image_start = 0;                /* starting block # of image */
+
+int rd_loading = 0;
+
+/*
+ *  Basically, my strategy here is to set up a buffer-head which can't be
+ *  deleted, and make that my Ramdisk.  If the request is outside of the
+ *  allocated size, we must get rid of it...
+ *
+ */
+static void rd_request(void)
+{
+       unsigned int minor;
+       int offset, len;
+
+repeat:
+       INIT_REQUEST;
+       
+       minor = MINOR(CURRENT->rq_dev);
+
+       if (minor >= NUM_RAMDISKS) {
+               end_request(0);
+               goto repeat;
+       }
+       
+       offset = CURRENT->sector << 9;
+       len = CURRENT->current_nr_sectors << 9;
+
+       if ((offset + len) > rd_length[minor]) {
+               end_request(0);
+               goto repeat;
+       }
+
+       if (CURRENT->cmd == READ) {     
+               memset(CURRENT->buffer, 0, len); 
+       }
+       set_bit(BH_Protected, &CURRENT->bh->b_state);
+
+       end_request(1);
+       goto repeat;
+} 
+
+static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int err;
+       
+       if (!inode || !inode->i_rdev)   
+               return -EINVAL;
+
+       switch (cmd) {
+               case BLKFLSBUF:
+                       if (!suser()) return -EACCES;
+                       invalidate_buffers(inode->i_rdev);
+                       break;
+               case BLKGETSIZE:   /* Return device size */
+                       if (!arg)  return -EINVAL;
+                       err = verify_area(VERIFY_WRITE, (long *) arg,
+                                         sizeof(long));
+                       if (err)
+                               return err;
+                       put_user(rd_length[MINOR(inode->i_rdev)] / 512, 
+                                (long *) arg);
+                       return 0;
+                       
+               default:
+                       break;
+       };
+
+       return 0;
+}
+
+static int rd_open(struct inode * inode, struct file * filp)
+{
+
+       if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
+               return -ENODEV;
+
+       return 0;
+}
+
+static struct file_operations fd_fops = {
+       NULL,           /* lseek - default */
+       block_read,     /* read - block dev write */
+       block_write,    /* write - block dev write */
+       NULL,           /* readdir - not here! */
+       NULL,           /* select */
+       rd_ioctl,       /* ioctl */
+       NULL,           /* mmap */
+       rd_open,        /* open */
+       NULL,           /* no special release code... */
+       block_fsync             /* fsync */ 
+};
+
+/* This is the registration and initialization section of the ramdisk driver */
+int rd_init(void)
+{
+       int             i;
+
+       if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
+               printk("RAMDISK2 : Could not get major %d", MAJOR_NR);
+               return -EIO;
+       }
+
+       blk_dev[MAJOR_NR].request_fn = &rd_request;
+
+       for (i = 0; i < NUM_RAMDISKS; i++) {
+               rd_length[i] = (16384 * 1024);
+               rd_blocksizes[i] = 1024;
+       }
+
+       blksize_size[MAJOR_NR] = rd_blocksizes;
+
+       return 0;
+}
+
+/*
+ * This routine tries to a ramdisk image to load, and returns the
+ * number of blocks to read for a non-compressed image, 0 if the image
+ * is a compressed image, and -1 if an image with the right magic
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
+ *     minix
+ *     ext2
+ *     gzip
+ */
+int
+identify_ramdisk_image(int device, struct file *fp, int start_block)
+{
+       const int size = 512;
+       struct minix_super_block *minixsb;
+       struct ext2_super_block *ext2sb;
+       int nblocks = -1;
+       int max_blocks;
+       unsigned char *buf;
+
+       buf = kmalloc(size, GFP_KERNEL);
+       if (buf == 0)
+               return -1;
+
+       minixsb = (struct minix_super_block *) buf;
+       ext2sb = (struct ext2_super_block *) buf;
+       memset(buf, 0xe5, size);
+
+       /*
+        * Read block 0 to test for gzipped kernel
+        */
+       if (fp->f_op->lseek)
+               fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+       fp->f_pos = start_block * BLOCK_SIZE;
+       
+       fp->f_op->read(fp->f_inode, fp, buf, size);
+
+       /*
+        * If it matches the gzip magic numbers, return -1
+        */
+       if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
+               printk(KERN_NOTICE
+                      "RAMDISK: Compressed image found at block %d\n",
+                      start_block);
+               nblocks = 0;
+               goto done;
+       }
+
+       /*
+        * Read block 1 to test for minix and ext2 superblock
+        */
+       if (fp->f_op->lseek)
+               fp->f_op->lseek(fp->f_inode, fp,
+                               (start_block+1) * BLOCK_SIZE, 0);
+       fp->f_pos = (start_block+1) * BLOCK_SIZE;
+
+       fp->f_op->read(fp->f_inode, fp, buf, size);
+               
+       /* Try minix */
+       if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
+           minixsb->s_magic == MINIX_SUPER_MAGIC2) {
+               printk(KERN_NOTICE
+                      "RAMDISK: Minix filesystem found at block %d\n",
+                      start_block);
+               nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
+               goto done;
+       }
+
+       /* Try ext2 */
+       printk("ext2 magic = %d\n", ext2sb->s_magic);
+       if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
+               printk(KERN_NOTICE
+                      "RAMDISK: Ext2 filesystem found at block %d\n",
+                      start_block);
+               nblocks = ext2sb->s_blocks_count;
+               goto done;
+       }
+       printk(KERN_NOTICE
+              "RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
+              start_block);
+       
+done:
+       if (fp->f_op->lseek)
+               fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+       fp->f_pos = start_block * BLOCK_SIZE;   
+
+       if ((nblocks > 0) && blk_size[MAJOR(device)]) {
+               max_blocks = blk_size[MAJOR(device)][MINOR(device)];
+               max_blocks -= start_block;
+               if (nblocks > max_blocks) {
+                       printk(KERN_NOTICE
+                              "RAMDISK: Restricting filesystem size "
+                              "from %d to %d blocks.\n",
+                              nblocks, max_blocks);
+                       nblocks = max_blocks;
+               }
+       }
+       kfree(buf);
+       return nblocks;
+}
+
+/*
+ * This routine loads in the ramdisk image.
+ */
+void rd_load()
+{
+       struct inode inode, out_inode;
+       struct file infile, outfile;
+       unsigned short fs;
+       int device, ram_device;
+       int nblocks, i;
+       char *buf;
+
+       if (rd_doload == 0)
+               return;
+       
+       device = ROOT_DEV;
+       ram_device = (MAJOR_NR << 8);
+
+       if (MAJOR(device) != FLOPPY_MAJOR) return;
+
+       if (rd_prompt) {
+               printk(KERN_NOTICE
+                      "VFS: Insert ramdisk floppy and press ENTER\n");
+               wait_for_keypress();
+       }
+
+       memset(&infile, 0, sizeof(infile));
+       memset(&inode, 0, sizeof(inode));
+       inode.i_rdev = device;
+       infile.f_mode = 1; /* read only */
+       infile.f_inode = &inode;
+
+       memset(&outfile, 0, sizeof(outfile));
+       memset(&out_inode, 0, sizeof(out_inode));
+       out_inode.i_rdev = ram_device;
+       outfile.f_mode = 3; /* read/write */
+       outfile.f_inode = &out_inode;
+
+       if (blkdev_open(&inode, &infile) != 0) return;
+       if (blkdev_open(&out_inode, &outfile) != 0) return;
+
+       fs = get_fs();
+       set_fs(KERNEL_DS);
+       rd_loading = 1;
+       
+       nblocks = identify_ramdisk_image(device, &infile, rd_image_start);
+       if (nblocks < 0)
+               goto done;
+
+       if (nblocks == 0) {
+#ifdef BUILD_CRAMDISK
+               if (crd_load(&infile, &outfile) == 0)
+                       goto successful_load;
+#else
+               printk(KERN_NOTICE
+                      "RAMDISK: Kernel does not support compressed "
+                      "ramdisk images\n");
+#endif
+               goto done;
+       }
+
+       if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) {
+               printk("RAMDISK: image too big! (%d/%d blocks)\n",
+                      nblocks, rd_length[0] >> BLOCK_SIZE_BITS);
+               goto done;
+       }
+               
+       /*
+        * OK, time to copy in the data
+        */
+       buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
+       if (buf == 0) {
+               printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
+               goto done;
+       }
+       for (i=0; i < nblocks; i++) {
+               infile.f_op->read(infile.f_inode, &infile, buf,
+                                 BLOCK_SIZE);
+               outfile.f_op->write(outfile.f_inode, &outfile, buf,
+                                   BLOCK_SIZE);
+       }
+       kfree(buf);
+
+successful_load:
+       invalidate_buffers(ROOT_DEV);
+       ROOT_DEV = (MAJOR_NR << 8);
+
+done:
+       if (infile.f_op->release)
+               infile.f_op->release(&inode, &infile);
+       set_fs(fs);
+       rd_loading = 0;
+}
+
+#ifdef BUILD_CRAMDISK
+
+#include <string.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000    /* window size--must be a power of two, and */
+                       /*  at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+static exit_code = 0;
+static long bytes_out = 0;
+static struct file *crd_infp, *crd_outfp;
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+               
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#include "../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+       return kmalloc(size, GFP_KERNEL);
+}
+
+static void free(void *where)
+{
+       kfree(where);
+}
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf()
+{
+       if (exit_code) return -1;
+       
+       insize = crd_infp->f_op->read(crd_infp->f_inode, crd_infp,
+                                     inbuf, INBUFSIZ);
+       if (insize == 0) return -1;
+
+       inptr = 1;
+
+       return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window()
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, ch;
+    
+    crd_outfp->f_op->write(crd_outfp->f_inode, crd_outfp, window,
+                          outcnt);
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+           ch = *in++;
+           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void error(char *x)
+{
+       printk(KERN_ERR "%s", x);
+       exit_code = 1;
+}
+
+static int
+crd_load(struct file * fp, struct file *outfp)
+{
+       int result;
+       
+       crd_infp = fp;
+       crd_outfp = outfp;
+       inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
+       if (inbuf == 0) {
+               printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
+               return -1;
+       }
+       window = kmalloc(WSIZE, GFP_KERNEL);
+       if (window == 0) {
+               printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
+               kfree(inbuf);
+               return -1;
+       }
+       makecrc();
+       result = gunzip();
+       kfree(inbuf);
+       kfree(window);
+       return result;
+}
+
+#endif
+
+
+
index d83765ac2ab26eb5af306278dcb87050592a9a36..07ed2bbc42ac7f3da9ea45645edceae245bc5b68 100644 (file)
  *     - much better than its 1Gig cousin, this drive is reported to work
  *       very well with DMA (7.3MB/sec).
  *
+ * Other drives:
+ *
+ *   Maxtor 7540AV (515Meg w/32kB buffer), DMA modes mword0/sword2, PIO mode3.
+ *     - a budget drive, with budget performance, around 3MB/sec.
+ *
+ *   Western Digital AC2850F (814Meg w/64kB buffer), DMA mode1, PIO mode3.
+ *     - another "caviar" drive, similar to the AC31000, except that this one
+ *       worked with DMA in at least one system.  Throughput is about 3.8MB/sec
+ *       for both DMA and PIO.
+ *
+ *   Conner CFS850A (812Meg w/64kB buffer), DMA mode2, PIO mode4.
+ *     - like most Conner models, this drive proves that even a fast interface
+ *       cannot improve slow media.  Both DMA and PIO peak around 3.5MB/sec.
+ *
  * If you have any drive models to add, email your results to:  mlord@bnr.ca
  * Keep an eye on /var/adm/messages for "DMA disabled" messages.
  *
index 44f5651c9be5e5d9f70db2cf301e3ed33733484b..4ff307d3de4d1fc1305bff24722b5a0ead35527a 100644 (file)
  */
 
 #include <linux/major.h>
-#include <linux/config.h>
 
 #include <linux/module.h>
 
index 097c5592c764d0861c1d810500695cb26f0778a5..70a92d3eaab67301cf5ed64e54fb5682ee6b398d 100644 (file)
 #include <asm/segment.h>
 #include <stdarg.h>
 #include <linux/sbpcd.h>
+#include <linux/config.h>
 
 #if !(SBPCD_ISSUE-1)
 #define MAJOR_NR MATSUSHITA_CDROM_MAJOR
index 6e9a7dfcae6cbdbc77ba4a24db7d501860413562..dbd2ba75c90ed89d86d982fc931f8b71d6c900cc 100644 (file)
@@ -1,3 +1,14 @@
+Tue Dec  5 13:21:27 1995    <tytso@rsts-11.mit.edu>
+
+       * serial.c (check_modem_status, rs_ioctl): Support the new
+               ioctl()'s TIOCGICOUNT, TIOCMIWAIT.  These allow an
+               application program to wait on a modem serial register
+               status bit change, and to find out how many changes have
+               taken place for the MSR bits.
+
+               (rs_write): Eliminate a race condition which is introduced
+               if it is necessary to wait for the semaphore.
+
 Sat Nov  4 17:14:45 1995    <tytso@rsts-11.mit.edu>
 
        * tty_io.c (tty_init): Move registration of TTY_MAJOR and
index e612af5e59233ef32896b5e675eaa4ece6c4a14e..8ebc156b43937ad9f8e56bd6e6eaea5d42ae1fd9 100644 (file)
@@ -30,6 +30,7 @@
  * Replaced dumb busy loop with udelay()  16 Nov 95
  *   Nathan Laredo <laredo@gnu.ai.mit.edu>
  *
+ * Track I/O ports with request_region().  12 Dec 95 Philip Blundell 
  */
 
 #include <linux/module.h>
@@ -43,6 +44,7 @@
 #include <linux/mouse.h>
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/ioport.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -137,7 +139,7 @@ static int open_mouse(struct inode * inode, struct file * file)
                return -EINVAL;
        if (mouse.active++)
                return 0;
-       if (request_irq(mouse_irq, mouse_interrupt, 0, "Busmouse")) {
+       if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse")) {
                mouse.active--;
                return -EBUSY;
        }
@@ -242,7 +244,10 @@ static struct mouse bus_mouse = {
 
 int bus_mouse_init(void)
 {
-       int i;
+       if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) {
+         mouse.present = 0;
+         return -EIO;
+       }
 
        outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
        outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
@@ -253,6 +258,9 @@ int bus_mouse_init(void)
        }
        outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
        MSE_INT_OFF();
+       
+       request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse");
+
        mouse.present = 1;
        mouse.active = 0;
        mouse.ready = 0;
@@ -260,7 +268,7 @@ int bus_mouse_init(void)
        mouse.dx = 0;
        mouse.dy = 0;
        mouse.wait = NULL;
-       printk("Logitech Bus mouse detected and installed with IRQ %d.\n",
+       printk("Logitech bus mouse detected, using IRQ %d.\n",
               mouse_irq);
        mouse_register(&bus_mouse);
        return 0;
@@ -276,5 +284,6 @@ int init_module(void)
 void cleanup_module(void)
 {
        mouse_deregister(&bus_mouse);
+       release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 }
 #endif
index 115e6b16bacaf02d8937c7370e1a29311611f8f7..6a4e07437926b40332d5b763a77cdac55f9f6e88 100644 (file)
@@ -11,6 +11,8 @@
  *  set_serial_info fixed to set the flags, custom divisor, and uart
  *     type fields.  Fix suggested by Michael K. Johnson 12/12/92.
  *
+ *  TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
+ *
  * This module exports the following rs232 io functions:
  *
  *     int rs_init(void);
@@ -455,6 +457,19 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
        
        status = serial_in(info, UART_MSR);
 
+       if (status & UART_MSR_ANY_DELTA) {
+               /* update input line counters */
+               if (status & UART_MSR_TERI)
+                       info->icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       info->icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       info->icount.dcd++;
+               if (status & UART_MSR_DCTS)
+                       info->icount.cts++;
+               wake_up_interruptible(&info->delta_msr_wait);
+       }
+
        if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
                printk("ttys%d CD now %s...", info->line,
@@ -1304,6 +1319,8 @@ static int rs_write(struct tty_struct * tty, int from_user,
        if (!tty || !info->xmit_buf || !tmp_buf)
                return 0;
            
+       if (from_user)
+               down(&tmp_buf_sem);
        save_flags(flags);
        while (1) {
                cli();          
@@ -1313,12 +1330,10 @@ static int rs_write(struct tty_struct * tty, int from_user,
                        break;
 
                if (from_user) {
-                       down(&tmp_buf_sem);
                        memcpy_fromfs(tmp_buf, buf, c);
                        c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
                                       SERIAL_XMIT_SIZE - info->xmit_head));
                        memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-                       up(&tmp_buf_sem);
                } else
                        memcpy(info->xmit_buf + info->xmit_head, buf, c);
                info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -1328,6 +1343,8 @@ static int rs_write(struct tty_struct * tty, int from_user,
                count -= c;
                total += c;
        }
+       if (from_user)
+               up(&tmp_buf_sem);
        if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
            !(info->IER & UART_IER_THRI)) {
                info->IER |= UART_IER_THRI;
@@ -1843,13 +1860,16 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        int error;
        struct async_struct * info = (struct async_struct *)tty->driver_data;
        int retval;
+       struct async_icount cprev, cnow;        /* kernel counter temps */
+       struct serial_icounter_struct *p_cuser; /* user space */
 
        if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
                return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
            (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
-           (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+           (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&
+           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -1949,6 +1969,55 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                case TIOCSERSETMULTI:
                        return set_multiport_struct(info,
                                       (struct serial_multiport_struct *) arg);
+               /*
+                * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+                * - mask passed in arg for lines of interest
+                *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+                * Caller should use TIOCGICOUNT to see which one it was
+                */
+                case TIOCMIWAIT:
+                       cli();
+                       cprev = info->icount;   /* note the counters on entry */
+                       sti();
+                       while (1) {
+                               interruptible_sleep_on(&info->delta_msr_wait);
+                               /* see if a signal did it */
+                               if (current->signal & ~current->blocked)
+                                       return -ERESTARTSYS;
+                               cli();
+                               cnow = info->icount;    /* atomic copy */
+                               sti();
+                               if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                                    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+                                    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+                                    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+                                       return 0;
+                               }
+                               cprev = cnow;
+                       }
+                       /* NOTREACHED */
+
+               /* 
+                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+                * Return: write counters to the user passed counter struct
+                * NB: both 1->0 and 0->1 transitions are counted except for
+                *     RI where only 0->1 is counted.
+                */
+               case TIOCGICOUNT:
+                       error = verify_area(VERIFY_WRITE, (void *) arg,
+                               sizeof(struct serial_icounter_struct));
+                       if (error)
+                               return error;
+                       cli();
+                       cnow = info->icount;
+                       sti();
+                       p_cuser = (struct serial_icounter_struct *) arg;
+                       put_user(cnow.cts, &p_cuser->cts);
+                       put_user(cnow.dsr, &p_cuser->dsr);
+                       put_user(cnow.rng, &p_cuser->rng);
+                       put_user(cnow.dcd, &p_cuser->dcd);
+                       return 0;
+
                default:
                        return -ENOIOCTLCMD;
                }
@@ -2662,6 +2731,9 @@ int rs_init(void)
                info->normal_termios = serial_driver.init_termios;
                info->open_wait = 0;
                info->close_wait = 0;
+               info->delta_msr_wait = 0;
+               info->icount.cts = info->icount.dsr = 
+                       info->icount.rng = info->icount.dcd = 0;
                info->next_port = 0;
                info->prev_port = 0;
                if (info->irq == 2)
index 7dd2ae37ed44a1b19d6123f6225dd0eb39e7e96b..05ea32f6c7f1e2209cbd6cfe142b1c8c57b6b14a 100644 (file)
@@ -612,9 +612,7 @@ int ethdev_init(struct device *dev)
     
     dev->hard_start_xmit = &ei_start_xmit;
     dev->get_stats     = get_stats;
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list = &set_multicast_list;
-#endif
 
     ether_setup(dev);
         
index 07061ec0c71a8cbd44f3836d99a63a493ed06fcb..0d2b5109f2e0ef4c05ddc4f7282f26dee310d8c8 100644 (file)
@@ -716,9 +716,7 @@ de4x5_hw_init(struct device *dev, u_long iobase)
     dev->hard_start_xmit = &de4x5_queue_pkt;
     dev->stop = &de4x5_close;
     dev->get_stats = &de4x5_get_stats;
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list = &set_multicast_list;
-#endif
     dev->do_ioctl = &de4x5_ioctl;
     
     dev->mem_start = 0;
index 1a2ed0ebca3c0ba94651f0ff950e879cec627049..252117eb42f3616f0daadc804718fcb3fcc56ada 100644 (file)
@@ -625,9 +625,7 @@ ewrk3_hw_init(struct device *dev, short iobase)
       dev->hard_start_xmit = &ewrk3_queue_pkt;
       dev->stop = &ewrk3_close;
       dev->get_stats = &ewrk3_get_stats;
-#ifdef HAVE_MULTICAST
       dev->set_multicast_list = &set_multicast_list;
-#endif
       dev->do_ioctl = &ewrk3_ioctl;
 
       dev->mem_start = 0;
index 3bb1730f812eb51e932a0ab4aebafd70d540671c..9f44928ea80f16d98fc6408432ce3d60571b0977 100644 (file)
@@ -623,7 +623,6 @@ static struct enet_statistics *net_get_stats(struct device *dev)
                return &lp->stats;
 }
 
-#ifdef HAVE_MULTICAST
 /* Set or clear the multicast filter for this adaptor.
    As a side effect this routine must also initialize the device parameters.
    This is taken advantage of in open().
@@ -662,7 +661,6 @@ static void set_multicast_list(struct device *dev)
        }
 #endif
 }
-#endif
 
 void show_dma(void)
 {
index feb9306c8f5030a9a9657e3379eff6ad2190b2ce..2dcad21bec049a7d8fc779fdbd22335b0996e57c 100644 (file)
@@ -23,15 +23,15 @@ dep_tristate 'EATA-DMA (DPT, NEC, ATT, Olivetti) support' CONFIG_SCSI_EATA_DMA $
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
 dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
-bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380
+dep_tristate 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
 fi
 dep_tristate 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 $CONFIG_SCSI
-bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16
+dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
 dep_tristate 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC $CONFIG_SCSI
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
-bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128
+dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
 dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
 dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
 dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
index 166f0c2cf0dc7219acd48c5a02d9153357757611..6bc070201435e6ebf09ecbacdbf5ce9725fe72c4 100644 (file)
@@ -18,7 +18,7 @@ MX_OBJS  :=
 MOD_LIST_NAME := SCSI_MODULES
 SCSI_SRCS = $(wildcard $(L_OBJS:%.o=%.c))
 
-AHA152X        = -DDEBUG_AHA152X -DAUTOCONF -DSKIP_BIOSTEST -DIRQ=11
+AHA152X        = -DDEBUG_AHA152X -DAUTOCONF
 
 ifeq (${CFLAGS},)
 CFLAGS = -D__KERNEL__=1 \
@@ -170,6 +170,10 @@ endif
 
 ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),y)
 L_OBJS += g_NCR5380.o
+else
+  ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),m)
+  M_OBJS += g_NCR5380.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_NCR53C7xx),y)
@@ -182,6 +186,10 @@ endif
 
 ifeq ($(CONFIG_SCSI_PAS16),y)
 L_OBJS += pas16.o
+else
+  ifeq ($(CONFIG_SCSI_PAS16),m)
+  M_OBJS += pas16.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_SEAGATE),y)
@@ -211,6 +219,10 @@ endif
 
 ifeq ($(CONFIG_SCSI_T128),y)
 L_OBJS += t128.o
+else
+  ifeq ($(CONFIG_SCSI_T128),m)
+  M_OBJS += t128.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_ULTRASTOR),y)
index a60ce4d03efb40ec4092c0aca8b8f2c4aadf2dbb..03c4d6dcb53a4045c3d8ac70c93d31ffdb57d973 100644 (file)
@@ -1,5 +1,5 @@
 This file contains brief information about the SCSI tape driver.
-Last modified: Sun Sep 24 23:40:06 1995 by root@kai.makisara.fi
+Last modified: Sun Nov 26 12:54:21 1995 by root@kai.makisara.fi
 
 BASICS
 
@@ -43,7 +43,17 @@ a filemark to truncate a read request or that don't like backspacing.
 The buffer size is defined (in 1024 byte units) by ST_BUFFER_BLOCKS or
 at boot time. If this size is not enough, the driver tries to allocate
 a large enough temporary buffer that is released when the device is
-closed.
+closed. The maximum buffer size is defined by the kernel memory
+allocation (currently 256 kB for Alphas and 128 kB for other
+architectures).
+
+Allocation of the buffers is done at run-time when they are
+needed. Allocation of the specified number of buffers can be done at
+initialization if ST_RUNTIME_BUFFERS is defined non-zero. The
+advantage of run-time allocation is that memory is not wasted for
+buffers not being used. The disadvantage is that there may not be
+memory available at the time when a buffer is needed for the first
+time (once a buffer is allocated, it is not released).
 
 The maximum number of buffers allocated at initialization is defined by
 ST_MAX_BUFFERS. One buffer is allocated for each drive detected when
@@ -54,14 +64,10 @@ initialization (a SCSI adapter driver is loaded as a module). The
 default for ST_EXTRA_DEVS is two. The driver tries to allocate new
 buffers at run-time if necessary.
 
-Allocation of the buffers can be postponed to run-time if
-(ST_RUNTIME_BUFFERS). The advantage is that memory is not wasted for
-buffers not being used. The disadvantage is that there may not be
-memory available at the time when a buffer is needed for the first
-time (once a buffer is allocated, it is not released).
-
 The threshold for triggering asynchronous write in fixed block mode
-is defined by ST_WRITE_THRESHOLD.
+is defined by ST_WRITE_THRESHOLD. This may be optimized for each
+use pattern. The default triggers asynchronous write after three
+default sized writes (10 kB) from tar.
 
 
 BOOT TIME CONFIGURATION
index 1876721d2a92612bf0610237be890dfa69f963d0..24ef306f7af9b106e968465cfbac08c1d009fd4c 100644 (file)
@@ -1,6 +1,6 @@
 /* aha152x.c -- Adaptec AHA-152x driver
- * Author: Juergen E. Fischer, fischer@server.et-inf.fho-emden.de
- * Copyright 1993, 1994 Juergen E. Fischer
+ * Author: Juergen E. Fischer, fischer@et-inf.fho-emden.de
+ * Copyright 1993, 1994, 1995 Juergen E. Fischer
  *
  *
  * This driver is based on
@@ -8,22 +8,28 @@
  * which is
  *   Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
  *
-
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2, or (at your option) any
  * later version.
-
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
- * $Id: aha152x.c,v 1.9 1995/03/18 09:20:24 root Exp root $
  *
-
+ * $Id: aha152x.c,v 1.11 1995/12/06 21:18:35 fischer Exp $
+ *
  * $Log: aha152x.c,v $
+ * Revision 1.11  1995/12/06  21:18:35  fischer
+ * - some minor updates
+ *
+ * Revision 1.10  1995/07/22  19:18:45  fischer
+ * - support for 2 controllers
+ * - started synchronous data transfers (not working yet)
+ *
  * Revision 1.9  1995/03/18  09:20:24  root
  * - patches for PCMCIA and modules
  *
  * Revision 0.0  1993/08/14  19:54:25  root
  * empty function bodies; detect() works.
  *
-
+ *
  **************************************************************************
 
 
 
  PER-DEFINE CONFIGURABLE OPTIONS:
 
- AUTOCONF       : use configuration the controller reports (only 152x)
- IRQ            : override interrupt channel (9,10,11 or 12) (default 11)
- SCSI_ID        : override scsiid of AIC-6260 (0-7) (default 7)
- RECONNECT      : override target dis-/reconnection/multiple outstanding commands (default on)
- PARITY                : override parity check (default on)
- SKIP_BIOSTEST  : Don't test for BIOS signature (AHA-1510 or disabled BIOS)
- PORTBASE       : Force port base. Don't try to probe
+ AUTOCONF:
+   use configuration the controller reports (only 152x)
+
+ SKIP_BIOSTEST:
+   Don't test for BIOS signature (AHA-1510 or disabled BIOS)
+
+ SETUP0        { IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the first controller
+   
+ SETUP1        { IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the second controller
 
 
  LILO COMMAND LINE OPTIONS:
 
- aha152x=<PORTBASE>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>]]]]
+ aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]
 
  The normal configuration can be overridden by specifying a command line.
  When you do this, the BIOS test is skipped. Entered values have to be
- valid (known). Don't use values that aren't support under normal operation.
- If you think that you need other values: contact me.
+ valid (known). Don't use values that aren't supported under normal operation.
+ If you think that you need other values: contact me.  For two controllers
+ use the aha152x statement twice.
 
 
  REFERENCES USED:
 #include <linux/proc_fs.h>
 
 #include "aha152x.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
 
 struct proc_dir_entry proc_scsi_aha152x = {
     PROC_SCSI_AHA152X, 7, "aha152x",
@@ -241,25 +252,9 @@ struct proc_dir_entry proc_scsi_aha152x = {
 #endif
 #endif
 
-/* If auto configuration is disabled, IRQ, SCSI_ID and RECONNECT have to
-   be predefined */
-#if !defined(AUTOCONF)
-#if !defined(IRQ)
-#error undefined IRQ; define AUTOCONF or IRQ
-#endif
-#if !defined(SCSI_ID)
-#error undefined SCSI_ID; define AUTOCONF or SCSI_ID
-#endif
-#if !defined(RECONNECT)
-#error undefined RECONNECT; define AUTOCONF or RECONNECT
+#if !defined(AUTOCONF) && !defined(SETUP0)
+#error define AUTOCONF or SETUP0
 #endif
-#if !defined(PARITY)
-#error undefined PARITY; define AUTOCONF or PARITY
-#endif
-#endif
-
-/* I use this when I'm looking for weird bugs */
-#define DEBUG_TIMING 
 
 #if defined(DEBUG_AHA152X)
 
@@ -287,6 +282,7 @@ struct proc_dir_entry proc_scsi_aha152x = {
 #if 0
 #endif
 
+#define DEBUG_SELECTION
 #define DEBUG_PHASES
 #define DEBUG_RESET
 #define DEBUG_ABORT
@@ -297,66 +293,89 @@ struct proc_dir_entry proc_scsi_aha152x = {
 
 /* END OF DEFINES */
 
+extern long loops_per_sec;
+
 /* some additional "phases" for getphase() */
 #define P_BUSFREE  1
 #define P_PARITY   2
 
-static int port_base      = 0;
-static int this_host      = 0;
-static int can_disconnect = 0;
-static int can_doparity   = 0;
-static int commands       = 0;
+/* possible irq range */
+#define IRQ_MIN 9
+#define IRQ_MAX 12
+#define IRQS    IRQ_MAX-IRQ_MIN+1
 
-#ifdef DEBUG_AHA152X
-unsigned int aha152x_debug  = DEBUG_DEFAULT;
-#endif
+enum {
+  not_issued   = 0x0001,
+  in_selection = 0x0002,
+  disconnected = 0x0004,
+  aborted      = 0x0008,
+  sent_ident   = 0x0010,
+  in_other     = 0x0020,
+  in_sync      = 0x0040,
+  sync_ok      = 0x0080,
+};
 
 /* set by aha152x_setup according to the command line */
-static int setup_called    = 0;
-static int setup_portbase  = 0;
-static int setup_irq       = 0;
-static int setup_scsiid    = 0;
-static int setup_reconnect = 0;
-static int setup_doparity  = 0;
+static int  setup_count=0;
+static struct aha152x_setup {
+  char *conf;
+  int io_port;
+  int irq;
+  int scsiid;
+  int reconnect;
+  int parity;
+  int synchronous;
+#ifdef DEBUG_AHA152X
+  int debug;
+#endif
+} setup[2];
+
+static struct Scsi_Host *aha152x_host[IRQS];
+
+#define HOSTDATA(shpnt)   ((struct aha152x_hostdata *) &shpnt->hostdata)
+#define CURRENT_SC       (HOSTDATA(shpnt)->current_SC)
+#define ISSUE_SC         (HOSTDATA(shpnt)->issue_SC)
+#define DISCONNECTED_SC          (HOSTDATA(shpnt)->disconnected_SC)
+#define SYNCRATE         (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target])
+#define MSG(i)            (HOSTDATA(shpnt)->message[i])
+#define MSGLEN            (HOSTDATA(shpnt)->message_len)
+#define ADDMSG(x)        (MSG(MSGLEN++)=x)
+
+struct aha152x_hostdata {
+  Scsi_Cmnd     *issue_SC;
+  Scsi_Cmnd     *current_SC;
+  Scsi_Cmnd     *disconnected_SC;
+  int           aborting;
+  int           abortion_complete;
+  int           abort_result;
+  int           commands;
+  
+  int           reconnect;
+  int           parity;
+  int           synchronous;
+  unsigned char syncrate[8];
+  
+  unsigned char message[256];
+  int           message_len;
 
 #ifdef DEBUG_AHA152X
-static int setup_debug     = 0;
+  int           debug;
 #endif
-
-static char *setup_str = (char *)NULL;
-
-enum {
-   not_issued   = 0x01,
-   in_selection = 0x02,
-   disconnected = 0x04,
-   aborted      = 0x08,
-   sent_ident   = 0x10,
-   in_other     = 0x20,
 };
-/*
- * Command queues:
- * issue_SC        : commands that are queued to be issued 
- * current_SC      : command that's currently using the bus
- * disconnected_SC : commands that that have been disconnected 
- */
-static Scsi_Cmnd            *issue_SC        = NULL;
-static Scsi_Cmnd            *current_SC      = NULL;
-static Scsi_Cmnd            *disconnected_SC = NULL;
-
-static int aborting=0, abortion_complete=0, abort_result;
 
-void aha152x_intr( int irq, struct pt_regs * );
-void aha152x_done( int error );
-void aha152x_setup( char *str, int *ints );
+void aha152x_intr(int irq, struct pt_regs *);
+void aha152x_done(struct Scsi_Host *shpnt, int error);
+void aha152x_setup(char *str, int *ints);
+int aha152x_checksetup(struct aha152x_setup *setup);
 
-static void aha152x_reset_ports(void);
-static void aha152x_panic(const char *msg);
+static void aha152x_reset_ports(struct Scsi_Host *shpnt);
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg);
 
-static void disp_ports(void);
+static void disp_ports(struct Scsi_Host *shpnt);
 static void show_command(Scsi_Cmnd *ptr);
-static void show_queues(void);
-static void disp_enintr(void);
+static void show_queues(struct Scsi_Host *shpnt);
+static void disp_enintr(struct Scsi_Host *shpnt);
 
 #if defined(DEBUG_RACE)
 static void enter_driver(const char *);
@@ -369,10 +388,7 @@ static unsigned short ports[] =
   0x340,      /* default first */
   0x140
 };
-#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
-
-/* possible interrupt channels */
-static unsigned short irqs[] = { 9, 10, 11, 12, 0 };
+#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))
 
 #if !defined(SKIP_BIOSTEST)
 /* possible locations for the Adaptec BIOS */
@@ -385,10 +401,10 @@ static void *addresses[] =
   (void *) 0xd4000,
   (void *) 0xd8000,
   (void *) 0xe0000,
-  (void *) 0xf0000,
   (void *) 0xeb800,   /* VTech Platinum SMP */
+  (void *) 0xf0000,
 };
-#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( void * ))
+#define ADDRESS_COUNT (sizeof(addresses) / sizeof(void *))
 
 /* signatures for various AIC-6[23]60 based controllers.
    The point in detecting signatures is to avoid useless
@@ -408,14 +424,17 @@ static struct signature {
   { "Adaptec BIOS: ASW-B626",       0x0f, 22 },  /* on-board controller */
   { "Adaptec ASW-B626 S2",        0x2e6c, 19 },  /* on-board controller */
   { "Adaptec BIOS:AIC-6360",         0xc, 21 },  /* on-board controller */
-  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller with AIC-6360 */
+  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller  */
   { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },  /* Gigabyte Local-Bus-SCSI */
+  { "Adaptec BIOS:AVA-282X",         0xc, 21 },  /* Adaptec 282x */
+  { "Adaptec IBM Dock II SCSI",   0x2edd, 24 },  /* IBM Thinkpad Dock II */
+  { "Adaptec BIOS:AHA-1532P",       0x1c, 22 },  /* IBM Thinkpad Dock II SCSI */
 };
-#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
 #endif
 
 
-static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
+static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */
 {
    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 
@@ -426,7 +445,7 @@ static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
 /*
  *  queue services:
  */
-static inline void append_SC( Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
 {
   Scsi_Cmnd *end;
 
@@ -435,15 +454,13 @@ static inline void append_SC( Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
     *SC=new_SC;
   else
     {
-      for( end=*SC;
-          end->host_scribble;
-          end = (Scsi_Cmnd *) end->host_scribble )
+      for(end=*SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble)
        ;
       end->host_scribble = (unsigned char *) new_SC;
     }
 }
 
-static inline Scsi_Cmnd *remove_first_SC( Scsi_Cmnd **SC )
+static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
 {
   Scsi_Cmnd *ptr;
 
@@ -453,13 +470,13 @@ static inline Scsi_Cmnd *remove_first_SC( Scsi_Cmnd **SC )
   return ptr;
 }
 
-static inline Scsi_Cmnd *remove_SC( Scsi_Cmnd **SC, int target, int lun )
+static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
 {
   Scsi_Cmnd *ptr, *prev;
 
-  for( ptr=*SC, prev=NULL;
+  for(ptr=*SC, prev=NULL;
        ptr && ((ptr->target!=target) || (ptr->lun!=lun));
-       prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble )
+      prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
@@ -473,13 +490,13 @@ static inline Scsi_Cmnd *remove_SC( Scsi_Cmnd **SC, int target, int lun )
 /*
  * read inbound byte and wait for ACK to get low
  */
-static void make_acklow(void)
+static void make_acklow(struct Scsi_Host *shpnt)
 {
-  SETPORT( SXFRCTL0, CH1|SPIOEN );
+  SETPORT(SXFRCTL0, CH1|SPIOEN);
   GETPORT(SCSIDAT);
-  SETPORT( SXFRCTL0, CH1 );
+  SETPORT(SXFRCTL0, CH1);
 
-  while( TESTHI( SCSISIG, ACKI ) )
+  while(TESTHI(SCSISIG, ACKI))
     ;
 }
 
@@ -493,37 +510,36 @@ static void make_acklow(void)
  *   P_BUSFREE   BUS FREE phase detected
  *   P_PARITY    parity error in DATA phase
  */
-static int getphase(void)
+static int getphase(struct Scsi_Host *shpnt)
 {
   int phase, sstat1;
   
-  while( 1 )
+  while(1)
     {
       do
        {
-         while( !( ( sstat1 = GETPORT( SSTAT1 ) ) & (BUSFREE|SCSIRSTI|REQINIT ) ) )
+          while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT)))
            ;
-         if( sstat1 & BUSFREE )
+          if(sstat1 & BUSFREE)
            return P_BUSFREE;
-         if( sstat1 & SCSIRSTI )
+          if(sstat1 & SCSIRSTI)
            {
-             /* IBM drive responds with RSTI to RSTO */
              printk("aha152x: RESET IN\n");
-             SETPORT( SSTAT1, SCSIRSTI );
+              SETPORT(SSTAT1, SCSIRSTI);
            }
        }
-      while( TESTHI( SCSISIG, ACKI ) || TESTLO( SSTAT1, REQINIT ) );
+      while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT));
 
-      SETPORT( SSTAT1, CLRSCSIPERR );
+      SETPORT(SSTAT1, CLRSCSIPERR);
   
-      phase = GETPORT( SCSISIG ) & P_MASK ;
+      phase = GETPORT(SCSISIG) & P_MASK ;
 
-      if( TESTHI( SSTAT1, SCSIPERR ) )
+      if(TESTHI(SSTAT1, SCSIPERR))
        {
-         if( (phase & (CDO|MSGO))==0 )                         /* DATA phase */
+          if((phase & (CDO|MSGO))==0)                        /* DATA phase */
            return P_PARITY;
 
-         make_acklow();
+          make_acklow(shpnt);
        }
       else
        return phase;
@@ -531,148 +547,170 @@ static int getphase(void)
 }
 
 /* called from init/main.c */
-void aha152x_setup( char *str, int *ints)
+void aha152x_setup(char *str, int *ints)
 {
-  if(setup_called)
-    panic("aha152x: aha152x_setup called twice.\n");
-
-  setup_called=ints[0];
-  setup_str=str;
-
-  setup_portbase  = ints[0] >= 1 ? ints[1] : 0x340;
-  setup_irq       = ints[0] >= 2 ? ints[2] : 11;
-  setup_scsiid   = ints[0] >= 3 ? ints[3] : 7;
-  setup_reconnect = ints[0] >= 4 ? ints[4] : 1;
-  setup_doparity  = ints[0] >= 5 ? ints[5] : 1;
+  if(setup_count>2)
+    panic("aha152x: you can only configure up to two controllers\n");
+
+  setup[setup_count].conf        = str;
+  setup[setup_count].io_port     = ints[0] >= 1 ? ints[1] : 0x340;
+  setup[setup_count].irq         = ints[0] >= 2 ? ints[2] : 11;
+  setup[setup_count].scsiid      = ints[0] >= 3 ? ints[3] : 7;
+  setup[setup_count].reconnect   = ints[0] >= 4 ? ints[4] : 1;
+  setup[setup_count].parity      = ints[0] >= 5 ? ints[5] : 1;
+  setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */;
 #ifdef DEBUG_AHA152X
-  setup_debug     = ints[0] >= 6 ? ints[6] : DEBUG_DEFAULT;
+  setup[setup_count].debug       = ints[0] >= 7 ? ints[7] : DEBUG_DEFAULT;
+  if(ints[0]>7)
+    { 
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+                "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>,[,<DEBUG>]]]]]]\n");
+#else
+  if(ints[0]>6)
+    {
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+             "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]\n");
 #endif
+    }
+  else 
+    setup_count++;
 }
 
 /*
    Test, if port_base is valid.
  */
-static int aha152x_porttest(int port_base)
+static int aha152x_porttest(int io_port)
 {
   int i;
 
-  if(check_region(port_base, 0x20))
+  if(check_region(io_port, IO_RANGE))
     return 0;
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
+  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
   for(i=0; i<16; i++)
-    SETPORT( STACK, i );
+    SETPORT(io_port+O_STACK, i);
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
-  for(i=0; i<16 && GETPORT(STACK)==i; i++)
+  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
+  for(i=0; i<16 && GETPORT(io_port+O_STACK)==i; i++)
     ;
 
   return(i==16);
 }
 
+int aha152x_checksetup(struct aha152x_setup *setup)
+{
+  int i;
+  
+#ifndef PCMCIA
+  for(i=0; i<PORT_COUNT && (setup->io_port != ports[i]); i++)
+    ;
+  
+  if(i==PORT_COUNT)
+    return 0;
+#endif
+  
+  if(!aha152x_porttest(setup->io_port))
+    return 0;
+  
+  if((setup->irq < IRQ_MIN) && (setup->irq > IRQ_MAX))
+    return 0;
+  
+  if((setup->scsiid < 0) || (setup->scsiid > 7))
+    return 0;
+  
+  if((setup->reconnect < 0) || (setup->reconnect > 1))
+    return 0;
+  
+  if((setup->parity < 0) || (setup->parity > 1))
+    return 0;
+  
+  if((setup->synchronous < 0) || (setup->synchronous > 1))
+    return 0;
+  
+  return 1;
+}
+
+
 int aha152x_detect(Scsi_Host_Template * tpnt)
 {
-  int                 i, ok;
+  int                 i, j, ok;
 #if defined(AUTOCONF)
   aha152x_config      conf;
 #endif
-  int                 interrupt_level;
-  struct Scsi_Host    *hreg;
   
   tpnt->proc_dir = &proc_scsi_aha152x;
 
-  if(setup_called)
+  for(i=0; i<IRQS; i++)
+    aha152x_host[i] = (struct Scsi_Host *) NULL;
+  
+  if(setup_count)
     {
       printk("aha152x: processing commandline: ");
    
-#ifdef DEBUG_AHA152X
-      if(setup_called>6)
-#else
-      if(setup_called>5)
-#endif
+      for(i=0; i<setup_count; i++)
+        if(!aha152x_checksetup(&setup[i]))
        {
-         printk("\naha152x: %s\n", setup_str );
-#ifdef DEBUG_AHA152X
-         printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>[,<DEBUG>]]]]]\n");
-#else
-         printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>]]]]\n");
-#endif
-         panic("aha152x panics in line %d", __LINE__);
+                printk("\naha152x: %s\n", setup[i].conf);
+                printk("aha152x: invalid line (controller=%d)\n", i+1);
        }
 
-      port_base       = setup_portbase;
-      interrupt_level = setup_irq;
-      this_host       = setup_scsiid;
-      can_disconnect  = setup_reconnect;
-      can_doparity    = setup_doparity;
-#ifdef DEBUG_AHA152X
-      aha152x_debug   = setup_debug;
-#endif
-
-#ifndef PCMCIA
-      for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++)
-       ;
-
-      if(i==PORT_COUNT)
-       {
-         printk("unknown portbase 0x%03x\n", port_base);
-         panic("aha152x panics in line %d", __LINE__);
+      printk("ok\n");
        }
-#endif
 
-      if(!aha152x_porttest(port_base))
+#ifdef SETUP0
+  if(setup_count<2)
        {
-         printk("portbase 0x%03x fails probe\n", port_base);
-#ifdef PCMCIA
-         return 0;
-#else
-         panic("aha152x panics in line %d", __LINE__);
-#endif
-       }
+      struct aha152x_setup override = SETUP0;
 
-#ifndef PCMCIA
-      i=0;
-      while(irqs[i] && (interrupt_level!=irqs[i]))
-       i++;
-      if(!irqs[i])
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
        {
-         printk("illegal IRQ %d\n", interrupt_level);
-         panic("aha152x panics in line %d", __LINE__);
+                printk("\naha152x: SETUP0 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+                     override.io_port,
+                     override.irq,
+                     override.scsiid,
+                     override.reconnect,
+                     override.parity,
+                     override.synchronous);
        }
-#endif
-      
-      if( (this_host < 0) || (this_host > 7) )
-       {
-         printk("illegal SCSI ID %d\n", this_host);
-         panic("aha152x panics in line %d", __LINE__);
+        else
+          setup[setup_count++] = override;
        }
+#endif
 
-      if( (can_disconnect < 0) || (can_disconnect > 1) )
+#ifdef SETUP1
+  if(setup_count<2)
        {
-         printk("reconnect %d should be 0 or 1\n", can_disconnect);
-         panic("aha152x panics in line %d", __LINE__);
-       }
+      struct aha152x_setup override = SETUP1;
 
-      if( (can_doparity < 0) || (can_doparity > 1) )
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
        {
-         printk("parity %d should be 0 or 1\n", can_doparity);
-         panic("aha152x panics in line %d", __LINE__);
-       }
-      printk("ok\n");
+                printk("\naha152x: SETUP1 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+                      override.io_port,
+                      override.irq,
+                      override.scsiid,
+                      override.reconnect,
+                      override.parity,
+                      override.synchronous);
     }
   else
+          setup[setup_count++] = override;
+    }
+#endif
+  
+#if defined(AUTOCONF)
+  if(setup_count<2)
     {
 #if !defined(SKIP_BIOSTEST)
-      int j;
-
       ok=0;
-      for( i=0; i < ADDRESS_COUNT && !ok; i++)
-       for( j=0; (j < SIGNATURE_COUNT) && !ok; j++)
+      for(i=0; i < ADDRESS_COUNT && !ok; i++)
+            for(j=0; (j < SIGNATURE_COUNT) && !ok; j++)
          ok=!memcmp((void *) addresses[i]+signatures[j].sig_offset,
                     (void *) signatures[j].signature,
                     (int) signatures[j].sig_length);
 
-      if(!ok)
+      if(!ok && setup_count==0)
        return 0;
 
       printk("aha152x: BIOS test: passed, ");
@@ -680,137 +718,149 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
       printk("aha152x: ");
 #endif /* !SKIP_BIOSTEST */
  
-#if !defined(PORTBASE)
-      printk("porttest: ");
-      for( i=0; i<PORT_COUNT && !aha152x_porttest(ports[i]); i++)
-       ;
+      for(i=0; i<PORT_COUNT && setup_count<2; i++)
+            {
+              if((setup_count==1) && (setup[0].io_port == ports[i]))
+                continue;
 
-      if(i==PORT_COUNT)
+              if(aha152x_porttest(ports[i]))
        {
-         printk("failed\n");
-         return 0;
+                  setup[setup_count].io_port = ports[i];
+              
+                  conf.cf_port =
+                       (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB);
+              
+                  setup[setup_count].irq         = IRQ_MIN + conf.cf_irq;
+                  setup[setup_count].scsiid      = conf.cf_id;
+                  setup[setup_count].reconnect   = conf.cf_tardisc;
+                  setup[setup_count].parity      = !conf.cf_parity;
+                  setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */;
+                  setup[setup_count].debug       = DEBUG_DEFAULT;
+                  setup_count++;
+                }
        }
-      else
-       port_base=ports[i];
-      printk("ok, ");
-#else
-      port_base=PORTBASE;
-#endif /* !PORTBASE */
 
-#if defined(AUTOCONF)
+      printk("auto configuration: ok, ");
+    }
+#endif
 
-      conf.cf_port = (GETPORT(PORTA)<<8) + GETPORT(PORTB);
+  printk("detection complete\n");
 
-      interrupt_level = irqs[conf.cf_irq];
-      this_host       = conf.cf_id;
-      can_disconnect  = conf.cf_tardisc;
-      can_doparity    = !conf.cf_parity;
+  for(i=0; i<setup_count; i++)
+    {
+      struct Scsi_Host        *shpnt;
 
-      printk("auto configuration: ok, ");
+      shpnt = aha152x_host[setup[i].irq-IRQ_MIN] =
+        scsi_register(tpnt, sizeof(struct aha152x_hostdata));
 
-#endif /* AUTOCONF */
+      shpnt->io_port                     = setup[i].io_port;
+      shpnt->n_io_port                   = IO_RANGE;
+      shpnt->irq                         = setup[i].irq;
 
-#if defined(IRQ)
-      interrupt_level = IRQ; 
-#endif
+      ISSUE_SC                           = (Scsi_Cmnd *) NULL;
+      CURRENT_SC                         = (Scsi_Cmnd *) NULL;
+      DISCONNECTED_SC                    = (Scsi_Cmnd *) NULL;
 
-#if defined(SCSI_ID)
-      this_host = SCSI_ID;
-#endif
+      HOSTDATA(shpnt)->reconnect         = setup[i].reconnect;
+      HOSTDATA(shpnt)->parity            = setup[i].parity;
+      HOSTDATA(shpnt)->synchronous       = setup[i].synchronous;
+      HOSTDATA(shpnt)->debug             = setup[i].debug;
 
-#if defined(RECONNECT)
-      can_disconnect=RECONNECT;
-#endif
+      HOSTDATA(shpnt)->aborting          = 0;
+      HOSTDATA(shpnt)->abortion_complete = 0;
+      HOSTDATA(shpnt)->abort_result      = 0;
+      HOSTDATA(shpnt)->commands          = 0;
 
-#if defined(PARITY)
-      can_doparity=PARITY;
-#endif
-    }
+      HOSTDATA(shpnt)->message_len       = 0;
 
-  printk("detection complete\n");
+      for(j=0; j<8; j++)
+        HOSTDATA(shpnt)->syncrate[j] = 0;
  
-  ok = request_irq(interrupt_level, aha152x_intr, SA_INTERRUPT, "aha152x");
+      ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
   
   if(ok<0)
     {
       if(ok == -EINVAL)
        {
-          printk("aha152x: bad IRQ %d.\n", interrupt_level);
+              printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq);
           printk("         Contact author.\n");
        }
       else
-       if( ok == -EBUSY)
-         printk( "aha152x: IRQ %d already in use. Configure another.\n",
-                 interrupt_level);
+            if(ok == -EBUSY)
+              printk("aha152x%d: IRQ %d already in use. Configure another.\n",
+                    i, setup[i].irq);
        else
          {
-           printk( "\naha152x: Unexpected error code on requesting IRQ %d.\n",
-                   interrupt_level);
+                printk("\naha152x%d: Unexpected error code on"
+                      " requesting IRQ %d.\n", i, setup[i].irq);
            printk("         Contact author.\n");
          }
-      panic("aha152x: driver needs an IRQ.\n");
+          printk("aha152x: driver needs an IRQ.\n");
+          continue;
     }
 
-  SETPORT( SCSIID, this_host << 4 );
-  tpnt->this_id=this_host;
+      SETPORT(SCSIID, setup[i].scsiid << 4);
+      shpnt->this_id=setup[i].scsiid;
   
-  if(can_disconnect)
-    tpnt->can_queue=AHA152X_MAXQUEUE;
+      if(setup[i].reconnect)
+        shpnt->hostt->can_queue=AHA152X_MAXQUEUE;
 
   /* RESET OUT */
-  SETBITS(SCSISEQ, SCSIRSTO );
+      SETBITS(SCSISEQ, SCSIRSTO);
   do_pause(30);
-  CLRBITS(SCSISEQ, SCSIRSTO );
+      CLRBITS(SCSISEQ, SCSIRSTO);
   do_pause(60);
 
-  aha152x_reset(NULL);
-
-  printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=%s\n",
-        port_base,
-        interrupt_level,
-        this_host,
-        can_disconnect ? "enabled" : "disabled",
-        can_doparity ? "enabled" : "disabled");
-
-  request_region(port_base, 0x20, "aha152x");        /* Register */
-
-  hreg = scsi_register(tpnt, 0);
-  hreg->io_port = port_base;
-  hreg->n_io_port = 0x20;
-  hreg->irq = interrupt_level;
+      aha152x_reset_ports(shpnt);
+      
+      printk("aha152x%d: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d,"
+             " reconnect=%s, parity=%s, synchronous=%s\n",
+            i,
+             shpnt->io_port,
+             shpnt->irq,
+             shpnt->this_id,
+             HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->parity ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
+
+      request_region(shpnt->io_port, IO_RANGE, "aha152x");  /* Register */
   
   /* not expecting any interrupts */
   SETPORT(SIMODE0, 0);
   SETPORT(SIMODE1, 0);
 
-  SETBITS( DMACNTRL0, INTEN);
-  return 1;
+      SETBITS(DMACNTRL0, INTEN);
+    }
+  
+  return (setup_count>0);
 }
 
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
 
 #if defined(DEBUG_RACE)
   enter_driver("queue");
 #else
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
     printk("aha152x: queue(), ");
 #endif
 #endif
 
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
   {
-    printk( "SCpnt (target = %d lun = %d cmnd = ", SCpnt->target, SCpnt->lun);
+      printk("SCpnt (target = %d lun = %d cmnd = ",
+             SCpnt->target, SCpnt->lun);
     print_command(SCpnt->cmnd);
-    printk( ", cmd_len=%d, pieces = %d size = %u), ",
-           SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen );
-    disp_ports();
+      printk(", cmd_len=%d, pieces = %d size = %u), ",
+             SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
+      disp_ports(shpnt);
   }
 #endif
 
@@ -825,7 +875,8 @@ int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
   SCpnt->SCp.phase = not_issued;
   if (SCpnt->use_sg)
     {
-      SCpnt->SCp.buffer           = (struct scatterlist *)SCpnt->request_buffer;
+      SCpnt->SCp.buffer =
+        (struct scatterlist *) SCpnt->request_buffer;
       SCpnt->SCp.ptr              = SCpnt->SCp.buffer->address;
       SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
       SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
@@ -846,21 +897,21 @@ int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
   /* Turn led on, when this is the first command. */
   save_flags(flags);
   cli();
-  commands++;
-  if(commands==1)
-    SETPORT( PORTA, 1 );
+  HOSTDATA(shpnt)->commands++;
+  if(HOSTDATA(shpnt)->commands==1)
+    SETPORT(PORTA, 1);
 
 #if defined(DEBUG_QUEUES)
-  if(aha152x_debug & debug_queues)
-    printk("i+ (%d), ", commands );
+  if(HOSTDATA(shpnt)->debug & debug_queues)
+    printk("i+ (%d), ", HOSTDATA(shpnt)->commands);
 #endif
-  append_SC( &issue_SC, SCpnt);
+  append_SC(&ISSUE_SC, SCpnt);
   
   /* Enable bus free interrupt, when we aren't currently on the bus */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
     }
   restore_flags(flags);
 
@@ -872,11 +923,11 @@ int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 }
 
 /*
- *  We only support command in interrupt-driven fashion
+ *  We only support commands in interrupt-driven fashion
  */
-int aha152x_command( Scsi_Cmnd *SCpnt )
+int aha152x_command(Scsi_Cmnd *SCpnt)
 {
-  printk( "aha152x: interrupt driven driver; use aha152x_queue()\n" );
+  printk("aha152x: interrupt driven driver; use aha152x_queue()\n");
   return -1;
 }
 
@@ -884,8 +935,9 @@ int aha152x_command( Scsi_Cmnd *SCpnt )
  *  Abort a queued command
  *  (commands that are on the bus can't be aborted easily)
  */
-int aha152x_abort( Scsi_Cmnd *SCpnt)
+int aha152x_abort(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev;
 
@@ -893,16 +945,15 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
   cli();
 
 #if defined(DEBUG_ABORT)
-  if(aha152x_debug & debug_abort)
+  if(HOSTDATA(shpnt)->debug & debug_abort)
   { 
-    printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt );
-
-    show_queues();
+      printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);
+      show_queues(shpnt);
   }
 #endif
 
   /* look for command in issue queue */
-  for( ptr=issue_SC, prev=NULL;
+  for(ptr=ISSUE_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
@@ -913,7 +964,7 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
       if(prev)
        prev->host_scribble = ptr->host_scribble;
       else
-       issue_SC = (Scsi_Cmnd *) ptr->host_scribble;
+        ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;
       restore_flags(flags);
 
       ptr->host_scribble = NULL;
@@ -924,11 +975,11 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
 
   /* if the bus is busy or a command is currently processed,
      we can't do anything more */
-  if ( TESTLO(SSTAT1, BUSFREE) || (current_SC && current_SC!=SCpnt))
+  if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt))
     {
       /* fail abortion, if bus is busy */
 
-      if(!current_SC)
+      if(!CURRENT_SC)
        printk("bus busy w/o current command, ");
  
       restore_flags(flags);
@@ -937,56 +988,58 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
 
   /* bus is free */
 
-  if(current_SC)
+  if(CURRENT_SC)
   { 
     /* target entered bus free before COMMAND COMPLETE, nothing to abort */
     restore_flags(flags);
-    current_SC->result = DID_ERROR << 16;
-    current_SC->scsi_done(current_SC);
-    current_SC = (Scsi_Cmnd *) NULL;
+      CURRENT_SC->result = DID_ERROR << 16;
+      CURRENT_SC->scsi_done(CURRENT_SC);
+      CURRENT_SC = (Scsi_Cmnd *) NULL;
     return SCSI_ABORT_SUCCESS;
   }
 
   /* look for command in disconnected queue */
-  for( ptr=disconnected_SC, prev=NULL;
+  for(ptr=DISCONNECTED_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
-    if(!aborting)
+    if(!HOSTDATA(shpnt)->aborting)
       {
        /* dequeue */
        if(prev)
          prev->host_scribble = ptr->host_scribble;
        else
-         disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+          DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
   
        /* set command current and initiate selection,
           let the interrupt routine take care of the abortion */
-       current_SC     = ptr;
+        CURRENT_SC     = ptr;
        ptr->SCp.phase = in_selection|aborted;
-       SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
+        SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
+        
+        ADDMSG(ABORT);
   
        /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-       SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-       SETPORT( SIMODE1, ENSELTIMO );
+        SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+        SETPORT(SIMODE1, ENSELTIMO);
   
        /* Enable SELECTION OUT sequence */
-       SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+        SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
   
-       SETBITS( DMACNTRL0, INTEN );
-       abort_result=SCSI_ABORT_SUCCESS;
-       aborting++;
-       abortion_complete=0;
+        SETBITS(DMACNTRL0, INTEN);
+        HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+        HOSTDATA(shpnt)->aborting++;
+        HOSTDATA(shpnt)->abortion_complete=0;
 
        sti();  /* Hi Eric, guess what ;-) */
   
        /* sleep until the abortion is complete */
-       while(!abortion_complete)
+        while(!HOSTDATA(shpnt)->abortion_complete)
          barrier();
-       aborting=0;
-       return abort_result;
+        HOSTDATA(shpnt)->aborting=0;
+        return HOSTDATA(shpnt)->abort_result;
       }
     else
       {
@@ -1004,7 +1057,7 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
 /*
  *  Restore default values to the AIC-6260 registers and reset the fifos
  */
-static void aha152x_reset_ports(void)
+static void aha152x_reset_ports(struct Scsi_Host *shpnt)
 {
   /* disable interrupts */
   SETPORT(DMACNTRL0, RSTFIFO);
@@ -1012,7 +1065,7 @@ static void aha152x_reset_ports(void)
   SETPORT(SCSISEQ, 0);
 
   SETPORT(SXFRCTL1, 0);
-  SETPORT( SCSISIG, 0);
+  SETPORT(SCSISIG, 0);
   SETPORT(SCSIRATE, 0);
 
   /* clear all interrupt conditions */
@@ -1031,45 +1084,47 @@ static void aha152x_reset_ports(void)
   SETPORT(SXFRCTL0, CH1);
 
   /* enable interrupts */
-  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+  SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+  SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 }
 
 /*
  *  Reset registers, reset a hanging bus and
  *  kill active and disconnected commands for target w/o soft reset
  */
-int aha152x_reset(Scsi_Cmnd * __unused)
+int aha152x_reset(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev, *next;
 
-  aha152x_reset_ports();
+  aha152x_reset_ports(shpnt);
 
   /* Reset, if bus hangs */
-  if( TESTLO( SSTAT1, BUSFREE ) )
+  if(TESTLO(SSTAT1, BUSFREE))
     {
-       CLRBITS( DMACNTRL0, INTEN );
+       CLRBITS(DMACNTRL0, INTEN);
 
 #if defined(DEBUG_RESET)
-  if(aha152x_debug & debug_reset)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
   {
        printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
-       show_queues();
+           show_queues(shpnt);
   }
 #endif
 
-       if(current_SC && !current_SC->device->soft_reset)
+       ptr=CURRENT_SC;
+       if(ptr && !ptr->device->soft_reset)
         {
-          current_SC->host_scribble = NULL;
-          current_SC->result = DID_RESET << 16;
-          current_SC->scsi_done(current_SC);
-          current_SC=NULL;
+           ptr->host_scribble = NULL;
+           ptr->result = DID_RESET << 16;
+           ptr->scsi_done(CURRENT_SC);
+           CURRENT_SC=NULL;
         }
 
        save_flags(flags);
        cli();
-       prev=NULL; ptr=disconnected_SC;
+       prev=NULL; ptr=DISCONNECTED_SC;
        while(ptr)
         {
           if(!ptr->device->soft_reset)
@@ -1077,13 +1132,13 @@ int aha152x_reset(Scsi_Cmnd * __unused)
               if(prev)
                 prev->host_scribble = ptr->host_scribble;
               else
-                disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+                DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
 
               next = (Scsi_Cmnd *) ptr->host_scribble;
   
               ptr->host_scribble = NULL;
               ptr->result        = DID_RESET << 16;
-              ptr->scsi_done(ptr);
+               ptr->scsi_done(ptr);
   
               ptr = next; 
             }
@@ -1095,11 +1150,11 @@ int aha152x_reset(Scsi_Cmnd * __unused)
         }
        restore_flags(flags);
 
-#if defined( DEBUG_RESET )
-       if(aha152x_debug & debug_reset)
+#if defined(DEBUG_RESET)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
        {
         printk("commands on targets w/ soft-resets:\n");
-        show_queues();
+           show_queues(shpnt);
        }
 #endif
 
@@ -1109,10 +1164,10 @@ int aha152x_reset(Scsi_Cmnd * __unused)
        SETPORT(SCSISEQ, 0);
        do_pause(60);
 
-       SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-       SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+       SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+       SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-       SETPORT( DMACNTRL0, INTEN );
+       SETPORT(DMACNTRL0, INTEN);
     }
 
   return SCSI_RESET_SUCCESS;
@@ -1121,14 +1176,13 @@ int aha152x_reset(Scsi_Cmnd * __unused)
 /*
  * Return the "logical geometry"
  */
-int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array )
+int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
 {
   int size = disk->capacity;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
-    printk("aha152x_biosparam: dev=%s, size=%d, ",
-          kdevname(dev), size);
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
+    printk("aha152x_biosparam: dev=%s, size=%d, ", kdevname(dev), size);
 #endif
   
 /* I took this from other SCSI drivers, since it provides
@@ -1138,7 +1192,7 @@ int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array )
   info_array[2]=size>>11;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
   {
     printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
           info_array[0], info_array[1], info_array[2]);
@@ -1152,54 +1206,54 @@ int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array )
 /*
  *  Internal done function
  */
-void aha152x_done( int error )
+void aha152x_done(struct Scsi_Host *shpnt, int error)
 {
   unsigned long flags;
   Scsi_Cmnd *done_SC;
 
 #if defined(DEBUG_DONE)
-  if(aha152x_debug & debug_done)
+  if(HOSTDATA(shpnt)->debug & debug_done)
   {
     printk("\naha152x: done(), ");
-    disp_ports();
+    disp_ports(shpnt);
   }
 #endif
 
-  if (current_SC)
+  if (CURRENT_SC)
     {
 #if defined(DEBUG_DONE)
-      if(aha152x_debug & debug_done)
+      if(HOSTDATA(shpnt)->debug & debug_done)
        printk("done(%x), ", error);
 #endif
 
       save_flags(flags);
       cli();
 
-      done_SC = current_SC;
-      current_SC = NULL;
+      done_SC = CURRENT_SC;
+      CURRENT_SC = NULL;
 
       /* turn led off, when no commands are in the driver */
-      commands--;
-      if(!commands)
-       SETPORT( PORTA, 0 );                                  /* turn led off */
+      HOSTDATA(shpnt)->commands--;
+      if(!HOSTDATA(shpnt)->commands)
+        SETPORT(PORTA, 0);                                  /* turn led off */
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues) 
-       printk("ok (%d), ", commands);
+      if(HOSTDATA(shpnt)->debug & debug_queues) 
+        printk("ok (%d), ", HOSTDATA(shpnt)->commands);
 #endif
       restore_flags(flags);
 
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
        printk("BUS FREE loop, ");
 #endif
-      while( TESTLO( SSTAT1, BUSFREE ) )
+      while(TESTLO(SSTAT1, BUSFREE))
        ;
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
        printk("BUS FREE\n");
 #endif
 
@@ -1207,27 +1261,28 @@ void aha152x_done( int error )
       if(done_SC->scsi_done)
        {
 #if defined(DEBUG_DONE)
-         if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
            printk("calling scsi_done, ");
 #endif
-         done_SC->scsi_done( done_SC );
+          done_SC->scsi_done(done_SC);
 #if defined(DEBUG_DONE)
-         if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
            printk("done returned, ");
 #endif
        }
       else
-       panic( "aha152x: current_SC->scsi_done() == NULL" );
+        panic("aha152x: current_SC->scsi_done() == NULL");
     }
   else
-    aha152x_panic( "done() called outside of command" );
+    aha152x_panic(shpnt, "done() called outside of command");
 }
 
 /*
  * Interrupts handler (main routine of the driver)
  */
-void aha152x_intr( int irqno, struct pt_regs * regs )
+void aha152x_intr(int irqno, struct pt_regs * regs)
 {
+  struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
   unsigned int flags;
   int done=0, phase;
 
@@ -1235,7 +1290,7 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
   enter_driver("intr");
 #else
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
+  if(HOSTDATA(shpnt)->debug & debug_intr)
     printk("\naha152x: intr(), ");
 #endif
 #endif
@@ -1244,74 +1299,76 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
      INTEN has to be restored, when we're ready to leave
      intr(). To avoid race conditions we have to return
      immediately afterwards. */
-  CLRBITS( DMACNTRL0, INTEN);
+  CLRBITS(DMACNTRL0, INTEN);
   sti();  /* Yes, sti() really needs to be here */
 
   /* disconnected target is trying to reconnect.
      Only possible, if we have disconnected nexuses and
      nothing is occupying the bus.
   */
-  if( TESTHI( SSTAT0, SELDI ) &&
-      disconnected_SC &&
-      ( !current_SC || ( current_SC->SCp.phase & in_selection ) )
+  if(TESTHI(SSTAT0, SELDI) &&
+      DISCONNECTED_SC &&
+      (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection))
     )
     {
       int identify_msg, target, i;
 
       /* Avoid conflicts when a target reconnects
         while we are trying to connect to another. */
-      if(current_SC)
+      if(CURRENT_SC)
        {
 #if defined(DEBUG_QUEUES)
-         if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
          printk("i+, ");
 #endif
          save_flags(flags);
          cli();
-         append_SC( &issue_SC, current_SC);
-         current_SC=NULL;
+          append_SC(&ISSUE_SC, CURRENT_SC);
+          CURRENT_SC=NULL;
          restore_flags(flags);
        }
 
       /* disable sequences */
-      SETPORT( SCSISEQ, 0 );
-      SETPORT( SSTAT0, CLRSELDI );
-      SETPORT( SSTAT1, CLRBUSFREE );
+      SETPORT(SCSISEQ, 0);
+      SETPORT(SSTAT0, CLRSELDI);
+      SETPORT(SSTAT1, CLRBUSFREE);
 
 #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_queues|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases))
        printk("reselected, ");
 #endif
 
-      i = GETPORT(SELID) & ~(1 << this_host);
+      i = GETPORT(SELID) & ~(1 << shpnt->this_id);
       target=0;
       if(i)
-       for( ; (i & 1)==0; target++, i>>=1)
+        for(; (i & 1)==0; target++, i>>=1)
          ;
       else
-       aha152x_panic("reconnecting target unknown");
+        aha152x_panic(shpnt, "reconnecting target unknown");
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-       printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );
+      if(HOSTDATA(shpnt)->debug & debug_queues)
+        printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);
 #endif
-      SETPORT( SCSIID, (this_host << OID_) | target );
-      SETPORT( SCSISEQ, ENRESELI );
+      SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
+      SETPORT(SCSISEQ, ENRESELI);
+
+      if(TESTLO(SSTAT0, SELDI))
+        aha152x_panic(shpnt, "RESELI failed");
 
-      if(TESTLO( SSTAT0, SELDI ))
-       aha152x_panic("RESELI failed");
+      SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f);
 
-      SETPORT( SCSISIG, P_MSGI );
+      SETPORT(SCSISIG, P_MSGI);
 
       /* Get identify message */
-      if((i=getphase())!=P_MSGI)
+      if((i=getphase(shpnt))!=P_MSGI)
        {
          printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
-         aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
        }
-      SETPORT( SCSISEQ, 0 );
+      SETPORT(SCSISEQ, 0);
 
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
       identify_msg = GETPORT(SCSIBUS);
 
@@ -1319,87 +1376,87 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
        {
          printk("target=%d, inbound message (%02x) != IDENTIFY\n",
                 target, identify_msg);
-         aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
        }
 
-      make_acklow();
-      getphase();
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-       printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );
+      if(HOSTDATA(shpnt)->debug & debug_queues)
+        printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f);
 #endif
 
       save_flags(flags);
       cli();
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
+      if(HOSTDATA(shpnt)->debug & debug_queues)
        printk("d-, ");
 #endif
-      current_SC = remove_SC( &disconnected_SC,
+      CURRENT_SC = remove_SC(&DISCONNECTED_SC,
                              target,
-                             identify_msg & 0x3f );
+                            identify_msg & 0x3f);
 
-      if(!current_SC)
+      if(!CURRENT_SC)
        {
-         printk("lun=%d, ", identify_msg & 0x3f );
-         aha152x_panic("no disconnected command for that lun");
+          printk("lun=%d, ", identify_msg & 0x3f);
+          aha152x_panic(shpnt, "no disconnected command for that lun");
        }
 
-      current_SC->SCp.phase &= ~disconnected;
+      CURRENT_SC->SCp.phase &= ~disconnected;
       restore_flags(flags);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_RACE)
       leave_driver("(reselected) intr");
 #endif
-      SETBITS( DMACNTRL0, INTEN);
+      SETBITS(DMACNTRL0, INTEN);
       return;
     }
   
   /* Check, if we aren't busy with a command */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
       /* bus is free to issue a queued command */
-      if(TESTHI( SSTAT1, BUSFREE) && issue_SC)
+      if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC)
        {
          save_flags(flags);
          cli();
 #if defined(DEBUG_QUEUES)
-         if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
            printk("i-, ");
 #endif
-         current_SC = remove_first_SC( &issue_SC );
+          CURRENT_SC = remove_first_SC(&ISSUE_SC);
          restore_flags(flags);
 
 #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-         if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
            printk("issuing command, ");
 #endif
-         current_SC->SCp.phase = in_selection;
+          CURRENT_SC->SCp.phase = in_selection;
 
-  #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-         if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
-           printk("selecting %d, ", current_SC->target); 
-  #endif
-         SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
+#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
+            printk("selecting %d, ", CURRENT_SC->target); 
+#endif
+          SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
 
          /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
-         SETPORT( SXFRCTL1, can_doparity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
+          SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
 
          /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-         SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-         SETPORT( SIMODE1, ENSELTIMO );
+          SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+          SETPORT(SIMODE1, ENSELTIMO);
 
          /* Enable SELECTION OUT sequence */
-         SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+          SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
        
-  #if defined(DEBUG_RACE)
+#if defined(DEBUG_RACE)
          leave_driver("(selecting) intr");
-  #endif
-         SETBITS( DMACNTRL0, INTEN );
+#endif
+          SETBITS(DMACNTRL0, INTEN);
          return;
        }
 
@@ -1411,200 +1468,229 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
   /* the bus is busy with something */
 
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_ports();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_ports(shpnt);
 #endif
 
   /* we are waiting for the result of a selection attempt */
-  if(current_SC->SCp.phase & in_selection)
+  if(CURRENT_SC->SCp.phase & in_selection)
     {
-      if( TESTLO( SSTAT1, SELTO ) )
+      if(TESTLO(SSTAT1, SELTO))
        /* no timeout */
-       if( TESTHI( SSTAT0, SELDO ) )
+        if(TESTHI(SSTAT0, SELDO))
          {
            /* clear BUS FREE interrupt */
-           SETPORT( SSTAT1, CLRBUSFREE);
+            SETPORT(SSTAT1, CLRBUSFREE);
 
            /* Disable SELECTION OUT sequence */
-           CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+            CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
            /* Disable SELECTION OUT DONE interrupt */
            CLRBITS(SIMODE0, ENSELDO);
            CLRBITS(SIMODE1, ENSELTIMO);
 
-           if( TESTLO(SSTAT0, SELDO) )
+            if(TESTLO(SSTAT0, SELDO))
              {
                printk("aha152x: passing bus free condition\n");
 
 #if defined(DEBUG_RACE)
                leave_driver("(passing bus free) intr");
 #endif
-               SETBITS( DMACNTRL0, INTEN);
+               SETBITS(DMACNTRL0, INTEN);
 
-               if(current_SC->SCp.phase & aborted)
+               if(CURRENT_SC->SCp.phase & aborted)
                  {
-                   abort_result=SCSI_ABORT_ERROR;
-                   abortion_complete++;
+                   HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+                   HOSTDATA(shpnt)->abortion_complete++;
                  }
 
-               aha152x_done( DID_NO_CONNECT << 16 );
+               aha152x_done(shpnt, DID_NO_CONNECT << 16);
                return;
              }
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-           if(aha152x_debug & (debug_selection|debug_phases))
+            if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
              printk("SELDO (SELID=%x), ", GETPORT(SELID));
 #endif
 
            /* selection was done */
-           SETPORT( SSTAT0, CLRSELDO );
+            SETPORT(SSTAT0, CLRSELDO);
 
 #if defined(DEBUG_ABORT)
-           if((aha152x_debug & debug_abort) && (current_SC->SCp.phase & aborted))
+            if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted))
              printk("(ABORT) target selected, ");
 #endif
 
-           current_SC->SCp.phase &= ~in_selection;
-           current_SC->SCp.phase |= in_other;
+            CURRENT_SC->SCp.phase &= ~in_selection;
+            CURRENT_SC->SCp.phase |= in_other;
+
+            ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun));
+
+            if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous)
+              {
+                ADDMSG(EXTENDED_MESSAGE);
+                ADDMSG(3);
+                ADDMSG(EXTENDED_SDTR);
+               ADDMSG(50);
+                ADDMSG(8);
+
+                printk("outbound SDTR: ");
+                print_msg(&MSG(MSGLEN-5));
+
+               SYNCRATE=0x80;
+                CURRENT_SC->SCp.phase |= in_sync;
+              }
 
 #if defined(DEBUG_RACE)
            leave_driver("(SELDO) intr");
 #endif
+            SETPORT(SCSIRATE, SYNCRATE&0x7f);
 
-           SETPORT( SCSISIG, P_MSGO );
+            SETPORT(SCSISIG, P_MSGO);
 
-           SETPORT( SIMODE0, 0 );
-           SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
-           SETBITS( DMACNTRL0, INTEN);
+            SETPORT(SIMODE0, 0);
+            SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
+            SETBITS(DMACNTRL0, INTEN);
            return;
          }
        else
-         aha152x_panic("neither timeout nor selection\007");
+          aha152x_panic(shpnt, "neither timeout nor selection\007");
       else
        {
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-         if(aha152x_debug & (debug_selection|debug_phases))
+          if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
          printk("SELTO, ");
 #endif
          /* end selection attempt */
-         CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+          CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
          /* timeout */
-         SETPORT( SSTAT1, CLRSELTIMO );
+          SETPORT(SSTAT1, CLRSELTIMO);
 
-         SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-         SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-         SETBITS( DMACNTRL0, INTEN );
+          SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+          SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+          SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
          leave_driver("(SELTO) intr");
 #endif
 
-         if(current_SC->SCp.phase & aborted)
+          if(CURRENT_SC->SCp.phase & aborted)
            {
 #if defined(DEBUG_ABORT)
-             if(aha152x_debug & debug_abort)
+              if(HOSTDATA(shpnt)->debug & debug_abort)
                printk("(ABORT) selection timeout, ");
 #endif
-             abort_result=SCSI_ABORT_ERROR;
-             abortion_complete++;
+              HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+              HOSTDATA(shpnt)->abortion_complete++;
            }
 
-         if( TESTLO( SSTAT0, SELINGO ) )
+          if(TESTLO(SSTAT0, SELINGO))
            /* ARBITRATION not won */
-           aha152x_done( DID_BUS_BUSY << 16 );
+            aha152x_done(shpnt, DID_BUS_BUSY << 16);
          else
            /* ARBITRATION won, but SELECTION failed */
-           aha152x_done( DID_NO_CONNECT << 16 );
+            aha152x_done(shpnt, DID_NO_CONNECT << 16);
+
          return;
        }
     }
 
   /* enable interrupt, when target leaves current phase */
-  phase = getphase();
+  phase = getphase(shpnt);
   if(!(phase & ~P_MASK))                                      /* "real" phase */
     SETPORT(SCSISIG, phase);
   SETPORT(SSTAT1, CLRPHASECHG);
-  current_SC->SCp.phase =
-    (current_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16 );
+  CURRENT_SC->SCp.phase =
+    (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16);
 
   /* information transfer phase */
-  switch( phase )
+  switch(phase)
     {
     case P_MSGO:                                               /* MESSAGE OUT */
       {
-       unsigned char message;
+        int i, identify=0, abort=0;
 
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
-       if(aha152x_debug & (debug_intr|debug_msgo|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases))
          printk("MESSAGE OUT, ");
 #endif
-
-       if( current_SC->SCp.phase & aborted )
+        if(MSGLEN==0)
          {
-#if defined(DEBUG_MSGO) || defined(DEBUG_ABORT)
-           if(aha152x_debug & (debug_msgo|debug_abort))
-             printk("ABORT, ");
+            ADDMSG(MESSAGE_REJECT);
+#if defined(DEBUG_MSGO)
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("unexpected MSGO; rejecting, ");
 #endif
-           message=ABORT;
          }
-       else
-         /* If we didn't identify yet, do it. Otherwise there's nothing to do,
-            but reject (probably we got an message before, that we have to
-            reject (SDTR, WDTR, etc.) */
-         if( !(current_SC->SCp.phase & sent_ident))
-           {
-             message=IDENTIFY(can_disconnect,current_SC->lun);
+        
+        
+        CLRBITS(SXFRCTL0, ENDMA);
+        
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
+        
+        /* wait for data latch to become ready or a phase change */
+        while(TESTLO(DMASTAT, INTSTAT))
+          ;
+        
 #if defined(DEBUG_MSGO)
-             if(aha152x_debug & debug_msgo)
-               printk("IDENTIFY (reconnect=%s;lun=%d), ", 
-                       can_disconnect ? "enabled" : "disabled", current_SC->lun);
-#endif
+        if(HOSTDATA(shpnt)->debug & debug_msgo)
+          {
+            int i;
+            
+            printk("messages (");
+            for(i=0; i<MSGLEN; i+=print_msg(&MSG(i)), printk(" "))
+              ;
+            printk("), ");
            }
-         else
+#endif
+        
+        for(i=0; i<MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++)
            {
-             message=MESSAGE_REJECT;
 #if defined(DEBUG_MSGO)
-             if(aha152x_debug & debug_msgo)
-               printk("REJECT, ");
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("%x ", MSG(i));
 #endif
+            if(i==MSGLEN-1)
+              {
+                /* Leave MESSAGE OUT after transfer */
+                SETPORT(SSTAT1, CLRATNO);
            }
          
-       CLRBITS( SXFRCTL0, ENDMA);
+            SETPORT(SCSIDAT, MSG(i));
 
-       SETPORT( SIMODE0, 0 );
-       SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE );
+            make_acklow(shpnt);
+            getphase(shpnt);
 
-       /* wait for data latch to become ready or a phase change */
-       while( TESTLO( DMASTAT, INTSTAT ) )
-         ;
+            if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun))
+              identify++;
 
-       if( TESTHI( SSTAT1, PHASEMIS ) )
-         aha152x_panic("unable to send message");
+            if(MSG(i)==ABORT)
+              abort++;
 
-       /* Leave MESSAGE OUT after transfer */
-       SETPORT( SSTAT1, CLRATNO);
+          }
 
-       SETPORT( SCSIDAT, message );
+        MSGLEN=0;
 
-       make_acklow();
-       getphase();
+        if(MSGLEN>0)
+          aha152x_panic(shpnt, "oops, MSGLEN>0 !?");
 
-       if(message==IDENTIFY(can_disconnect,current_SC->lun))
-         current_SC->SCp.phase |= sent_ident;
+        if(identify)
+          CURRENT_SC->SCp.phase |= sent_ident;
 
-       if(message==ABORT)
+        if(abort)
          {
            /* revive abort(); abort() enables interrupts */
-           abort_result=SCSI_ABORT_SUCCESS;
-           abortion_complete++;
+            HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+            HOSTDATA(shpnt)->abortion_complete++;
 
-           current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+            CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
            /* exit */
-           SETBITS( DMACNTRL0, INTEN );
+            SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
            leave_driver("(ABORT) intr");
 #endif
-           aha152x_done(DID_ABORT<<16);
+            aha152x_done(shpnt, DID_ABORT<<16);
            return;
          }
       }
@@ -1612,291 +1698,263 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
 
     case P_CMD:                                          /* COMMAND phase */
 #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_cmd|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases))
        printk("COMMAND, ");
 #endif
-      if( !(current_SC->SCp.sent_command) )
+      if(!(CURRENT_SC->SCp.sent_command))
        {
-         if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
-           printk("aha152x: P_CMD: %d(%d) bytes left in FIFO, resetting\n",
-                  GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+          int i;
 
-         /* reset fifo and enable writes */
-         SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-         SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
+          CLRBITS(SXFRCTL0, ENDMA);
 
-         /* clear transfer count and scsi fifo */
-         SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
-         SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
+          SETPORT(SIMODE0, 0);
+          SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
   
-         /* missing phase raises INTSTAT */
-         SETPORT( SIMODE0, 0 );
-         SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
-  
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
-           printk("waiting, ");
-#endif
-         /* wait for FIFO to get empty */
-         while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
+          /* wait for data latch to become ready or a phase change */
+          while(TESTLO(DMASTAT, INTSTAT))
            ;
   
-         if( TESTHI( SSTAT1, PHASEMIS ) )
-           aha152x_panic("target left COMMAND phase");
-
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
+          for(i=0; i<CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++)
          {
-           printk("DFIFOEMP, outsw (%d bytes, %d words), ",
-                  current_SC->cmd_len, current_SC->cmd_len >> 1 );
-           disp_ports();
-         }
-#endif
-  
-         outsw( DATAPORT, &current_SC->cmnd, current_SC->cmd_len >> 1 );
+              SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]);
 
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
-         {
-           printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
-           disp_ports();
+              make_acklow(shpnt);
+              getphase(shpnt);
          }
-#endif
 
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
-           printk("waiting for SEMPTY, ");
-#endif
-
-         /* wait for SCSI FIFO to get empty.
-            very important to send complete commands. */
-         while( TESTLO ( SSTAT2, SEMPTY ) )
-           ;
-
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
-           printk("SEMPTY, ");
-#endif
-
-         CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-         /* transfer can be considered ended, when SCSIEN reads back zero */
-         while( TESTHI( SXFRCTL0, SCSIEN ) )
-           ;
-
-#if defined(DEBUG_CMD)
-         if(aha152x_debug & debug_cmd)
-           printk("!SEMPTY, ");
-#endif
-
-         CLRBITS(DMACNTRL0, ENDMA);
-
-#if defined(DEBUG_CMD) || defined(DEBUG_INTR)
-         if(debug_cmd & debug_intr)
-           printk("sent %d/%d command bytes, ", GETSTCNT(),
-                  current_SC->cmd_len);
-#endif
+          if(i<CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS))
+            aha152x_panic(shpnt, "target left COMMAND");
 
+          CURRENT_SC->SCp.sent_command++;
        }
       else
-       aha152x_panic("Nothing to sent while in COMMAND OUT");
+        aha152x_panic(shpnt, "Nothing to send while in COMMAND");
       break;
 
     case P_MSGI:                                          /* MESSAGE IN phase */
+      {
+        int start_sync=0;
+        
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_msgi|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases))
        printk("MESSAGE IN, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+        SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0);
-      SETPORT( SIMODE1, ENBUSFREE);
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENBUSFREE);
   
-      while( phase == P_MSGI 
+        while(phase == P_MSGI
        {
-         current_SC->SCp.Message = GETPORT( SCSIBUS );
-         switch(current_SC->SCp.Message)
+            CURRENT_SC->SCp.Message = GETPORT(SCSIDAT);
+            switch(CURRENT_SC->SCp.Message)
            {
            case DISCONNECT:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-             if(aha152x_debug & (debug_msgi|debug_phases))
+               if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
                printk("target disconnected, ");
 #endif
-             current_SC->SCp.Message = 0;
-             current_SC->SCp.phase   |= disconnected;
-             if(!can_disconnect)
-               aha152x_panic("target was not allowed to disconnect");
+               CURRENT_SC->SCp.Message = 0;
+               CURRENT_SC->SCp.phase   |= disconnected;
+               if(!HOSTDATA(shpnt)->reconnect)
+                 aha152x_panic(shpnt, "target was not allowed to disconnect");
              break;
        
            case COMMAND_COMPLETE:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-             if(aha152x_debug & (debug_msgi|debug_phases))
-               printk("inbound message ( COMMAND COMPLETE ), ");
+               if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
+                 printk("inbound message (COMMAND COMPLETE), ");
 #endif
              done++;
              break;
 
            case MESSAGE_REJECT:
+               if(CURRENT_SC->SCp.phase & in_sync)
+                 { 
+                   CURRENT_SC->SCp.phase &= ~in_sync;
+                   SYNCRATE=0x80;
+                   printk("synchronous rejected, ");
+                 }
+               else
+                 printk("inbound message (MESSAGE REJECT), ");
 #if defined(DEBUG_MSGI)
-             if(aha152x_debug & debug_msgi)
-               printk("inbound message ( MESSAGE REJECT ), ");
+               if(HOSTDATA(shpnt)->debug & debug_msgi)
+                 printk("inbound message (MESSAGE REJECT), ");
 #endif
              break;
 
            case SAVE_POINTERS:
 #if defined(DEBUG_MSGI)
-             if(aha152x_debug & debug_msgi)
-               printk("inbound message ( SAVE DATA POINTERS ), ");
+               if(HOSTDATA(shpnt)->debug & debug_msgi)
+                 printk("inbound message (SAVE DATA POINTERS), ");
 #endif
              break;
 
            case EXTENDED_MESSAGE:
              { 
-               int           i, code;
+                 char buffer[16];
+                 int  i;
 
 #if defined(DEBUG_MSGI)
-               if(aha152x_debug & debug_msgi)
-                 printk("inbound message ( EXTENDED MESSAGE ), ");
+                 if(HOSTDATA(shpnt)->debug & debug_msgi)
+                   printk("inbound message (EXTENDED MESSAGE), ");
 #endif
-               make_acklow();
-               if(getphase()!=P_MSGI)
+                 make_acklow(shpnt);
+                 if(getphase(shpnt)!=P_MSGI)
                  break;
   
-               i=GETPORT(SCSIBUS);
+                 buffer[0]=EXTENDED_MESSAGE;
+                 buffer[1]=GETPORT(SCSIDAT);
+                 
+                 for(i=0; i<buffer[1] &&
+                     (make_acklow(shpnt), getphase(shpnt)==P_MSGI); i++)
+                   buffer[2+i]=GETPORT(SCSIDAT);
 
 #if defined(DEBUG_MSGI)
-               if(aha152x_debug & debug_msgi)
-                 printk("length (%d), code ( ", i);
-#endif
-
-               make_acklow();
-               if(getphase()!=P_MSGI)
+                 if(HOSTDATA(shpnt)->debug & debug_msgi)
+                   print_msg(buffer);
+#endif
+
+                 switch(buffer [2])
+                   {
+                   case EXTENDED_SDTR:
+                     {
+                       long ticks;
+                       
+                       if(buffer[1]!=3)
+                         aha152x_panic(shpnt, "SDTR message length != 3");
+                       
+                       if(!HOSTDATA(shpnt)->synchronous)
                  break;
 
-               code = GETPORT(SCSIBUS);
+                       printk("inbound SDTR: "); print_msg(buffer);
+                       
+                       ticks=(buffer[3]*4+49)/50;
 
-               switch( code )
+                       if(CURRENT_SC->SCp.phase & in_sync)
                  {
-                 case 0x00:
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     printk("MODIFY DATA POINTER ");
-#endif
-                   SETPORT(SCSISIG, P_MSGI|ATNO);
-                   break;
-                 case 0x01:
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     printk("SYNCHRONOUS DATA TRANSFER REQUEST ");
-#endif
-                   SETPORT(SCSISIG, P_MSGI|ATNO);
-                   break;
-                 case 0x02:
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     printk("EXTENDED IDENTIFY ");
-#endif
-                   break;
-                 case 0x03:
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     printk("WIDE DATA TRANSFER REQUEST ");
-#endif
-                   SETPORT(SCSISIG, P_MSGI|ATNO);
-                   break;
-                 default:
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     if( code & 0x80 )
-                       printk("reserved (%d) ", code );
+                           /* we initiated SDTR */
+                           if(ticks>9 || buffer[4]<1 || buffer[4]>8)
+                             aha152x_panic(shpnt, "received SDTR invalid");
+                           
+                           SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+                         }
+                       else if(ticks<=9 && buffer[4]>=1)
+                         {
+                           if(buffer[4]>8)
+                             buffer[4]=8;
+                           
+                           ADDMSG(EXTENDED_MESSAGE);
+                           ADDMSG(3);
+                           ADDMSG(EXTENDED_SDTR);
+                           if(ticks<4)
+                             {
+                                   ticks=4;
+                                   ADDMSG(50);
+                             }
                      else
-                       printk("vendor specific (%d) ", code);
-#endif
-                   SETPORT(SCSISIG, P_MSGI|ATNO);
-                   break;
+                             ADDMSG(buffer[3]);
+                           
+                           ADDMSG(buffer[4]);
+                           
+                           printk("outbound SDTR: ");
+                            print_msg(&MSG(MSGLEN-5));
+                           
+                           CURRENT_SC->SCp.phase |= in_sync;
+                           
+                            SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+                           
+                           start_sync++;
                  }
-#if defined(DEBUG_MSGI)
-               if(aha152x_debug & debug_msgi)
-                 printk(" ), data ( ");
-#endif
-               while( --i && (make_acklow(), getphase()==P_MSGI))
+                       else
                  {
-#if defined(DEBUG_MSGI)
-                   if(aha152x_debug & debug_msgi)
-                     printk("%x ", GETPORT(SCSIBUS) );
-#else
-                   GETPORT(SCSIBUS);
-#endif
+                           /* request SDTR is to slow, do it asynchronously */
+                           ADDMSG(MESSAGE_REJECT);
+                            SYNCRATE = 0;
+                         } 
+                       
+                       SETPORT(SCSIRATE, SYNCRATE&0x7f);
+                     }
+                     break;
+                     
+                   case EXTENDED_MODIFY_DATA_POINTER:
+                   case EXTENDED_EXTENDED_IDENTIFY:
+                   case EXTENDED_WDTR:
+                   default:
+                     ADDMSG(MESSAGE_REJECT);
+                     break;
                  }
-#if defined(DEBUG_MSGI)
-               if(aha152x_debug & debug_msgi)
-                 printk(" ), ");
-#endif
-               /* We reject all extended messages. To do this
-                  we just enter MSGO by asserting ATN. Since
-                  we have already identified a REJECT message
-                  will be sent. */
-               SETPORT(SCSISIG, P_MSGI|ATNO);
              }
              break;
        
            default:
-             printk("unsupported inbound message %x, ", current_SC->SCp.Message);
+               printk("unsupported inbound message %x, ", 
+                      CURRENT_SC->SCp.Message);
              break;
 
            }
 
-         make_acklow();
-         phase=getphase();
+            make_acklow(shpnt);
+            phase=getphase(shpnt);
        } 
 
+        if(start_sync)
+          CURRENT_SC->SCp.phase |= in_sync;
+        else
+          CURRENT_SC->SCp.phase &= ~in_sync;
+        
+        if(MSGLEN>0)
+          SETPORT(SCSISIG, P_MSGI|ATNO);
+        
       /* clear SCSI fifo on BUSFREE */
       if(phase==P_BUSFREE)
        SETPORT(SXFRCTL0, CH1|CLRCH1);
 
-      if(current_SC->SCp.phase & disconnected)
+        if(CURRENT_SC->SCp.phase & disconnected)
        {
          save_flags(flags);
          cli();
 #if defined(DEBUG_QUEUES)
-         if(aha152x_debug & debug_queues)
+            if(HOSTDATA(shpnt)->debug & debug_queues)
            printk("d+, ");
 #endif
-         append_SC( &disconnected_SC, current_SC);
-         current_SC = NULL;
+            append_SC(&DISCONNECTED_SC, CURRENT_SC);
+            CURRENT_SC = NULL;
          restore_flags(flags);
 
-         SETBITS( SCSISEQ, ENRESELI );
+            SETBITS(SCSISEQ, ENRESELI);
 
-         SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-         SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+            SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+            SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-         SETBITS( DMACNTRL0, INTEN );
+            SETBITS(DMACNTRL0, INTEN);
          return;
        }
+      }
       break;
 
     case P_STATUS:                                         /* STATUS IN phase */
 #if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_status|debug_intr|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases))
        printk("STATUS, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
 
-      if( TESTHI( SSTAT1, PHASEMIS ) )
+      if(TESTHI(SSTAT1, PHASEMIS))
        printk("aha152x: passing STATUS phase");
        
-      current_SC->SCp.Status = GETPORT( SCSIBUS );
-      make_acklow();
-      getphase();
+      CURRENT_SC->SCp.Status = GETPORT(SCSIBUS);
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_STATUS)
-      if(aha152x_debug & debug_status)
+      if(HOSTDATA(shpnt)->debug & debug_status)
       {
        printk("inbound status ");
-       print_status( current_SC->SCp.Status );
+          print_status(CURRENT_SC->SCp.Status);
        printk(", ");
       }
 #endif
@@ -1907,117 +1965,130 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
        int fifodata, data_count, done;
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-       if(aha152x_debug & (debug_datai|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases))
          printk("DATA IN, ");
 #endif
 
+#if 0
        if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
          printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
                 GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+#endif
 
        /* reset host fifo */
        SETPORT(DMACNTRL0, RSTFIFO);
        SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
 
-       SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN );
+        SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
 
-       SETPORT( SIMODE0, 0 );
-       SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 
        /* done is set when the FIFO is empty after the target left DATA IN */
        done=0;
       
        /* while the target stays in DATA to transfer data */
-       while ( !done 
+        while (!done
          {
 #if defined(DEBUG_DATAI)
-           if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
              printk("expecting data, ");
 #endif
            /* wait for PHASEMIS or full FIFO */
-           while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) )
+            while(TESTLO (DMASTAT, DFIFOFULL|INTSTAT))
              ;
 
-           if( TESTHI( DMASTAT, DFIFOFULL ) )
+#if defined(DEBUG_DATAI)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
+              printk("ok, ");
+#endif
+            
+            if(TESTHI(DMASTAT, DFIFOFULL))
              fifodata=GETPORT(FIFOSTAT);
            else
              {
                /* wait for SCSI fifo to get empty */
-               while( TESTLO( SSTAT2, SEMPTY ) )
+               while(TESTLO(SSTAT2, SEMPTY))
                  ;
 
                /* rest of data in FIFO */
                fifodata=GETPORT(FIFOSTAT);
 #if defined(DEBUG_DATAI)
-               if(aha152x_debug & debug_datai)
+               if(HOSTDATA(shpnt)->debug & debug_datai)
                  printk("last transfer, ");
 #endif
                done=1;
              }
   
 #if defined(DEBUG_DATAI)
-           if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
              printk("fifodata=%d, ", fifodata);
 #endif
 
-           while( fifodata && current_SC->SCp.this_residual )
+            while(fifodata && CURRENT_SC->SCp.this_residual)
              {
                data_count=fifodata;
   
                /* limit data transfer to size of first sg buffer */
-               if (data_count > current_SC->SCp.this_residual)
-                 data_count = current_SC->SCp.this_residual;
+               if (data_count > CURRENT_SC->SCp.this_residual)
+                 data_count = CURRENT_SC->SCp.this_residual;
   
                fifodata -= data_count;
 
 #if defined(DEBUG_DATAI)
-               if(aha152x_debug & debug_datai)
+               if(HOSTDATA(shpnt)->debug & debug_datai)
                  printk("data_count=%d, ", data_count);
 #endif
   
                if(data_count&1)
                  {
                    /* get a single byte in byte mode */
-                   SETBITS(DMACNTRL0, _8BIT );
-                   *current_SC->SCp.ptr++ = GETPORT( DATAPORT );
-                   current_SC->SCp.this_residual--;
+                   SETBITS(DMACNTRL0, _8BIT);
+                   *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
+                   CURRENT_SC->SCp.this_residual--;
                  }
                if(data_count>1)
                  {
-                   CLRBITS(DMACNTRL0, _8BIT );
+                   CLRBITS(DMACNTRL0, _8BIT);
                    data_count >>= 1; /* Number of words */
-                   insw( DATAPORT, current_SC->SCp.ptr, data_count );
+                   insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
 #if defined(DEBUG_DATAI)
-                   if(aha152x_debug & debug_datai)
-/* show what comes with the last transfer */
+                   if(HOSTDATA(shpnt)->debug & debug_datai)
+                     /* show what comes with the last transfer */
                      if(done)
                        {
+#ifdef 0
                          int           i;
                          unsigned char *data;
+#endif
   
+                         printk("data on last transfer (%d bytes) ",
+                                2*data_count);
+#ifdef 0
                          printk("data on last transfer (%d bytes: ",
                                 2*data_count);
-                         data = (unsigned char *) current_SC->SCp.ptr;
-                         for( i=0; i<2*data_count; i++)
+                         data = (unsigned char *) CURRENT_SC->SCp.ptr;
+                         for(i=0; i<2*data_count; i++)
                            printk("%2x ", *data++);
                          printk("), ");
+#endif
                        }
 #endif
-                   current_SC->SCp.ptr           += 2 * data_count;
-                   current_SC->SCp.this_residual -= 2 * data_count;
+                   CURRENT_SC->SCp.ptr           += 2 * data_count;
+                   CURRENT_SC->SCp.this_residual -= 2 * data_count;
                  }
              
                /* if this buffer is full and there are more buffers left */
-               if (!current_SC->SCp.this_residual &&
-                    current_SC->SCp.buffers_residual)
+               if (!CURRENT_SC->SCp.this_residual &&
+                   CURRENT_SC->SCp.buffers_residual)
                  {
                    /* advance to next buffer */
-                   current_SC->SCp.buffers_residual--;
-                   current_SC->SCp.buffer++;
-                   current_SC->SCp.ptr =
-                     current_SC->SCp.buffer->address;
-                   current_SC->SCp.this_residual =
-                     current_SC->SCp.buffer->length;
+                   CURRENT_SC->SCp.buffers_residual--;
+                   CURRENT_SC->SCp.buffer++;
+                   CURRENT_SC->SCp.ptr =
+                     CURRENT_SC->SCp.buffer->address;
+                   CURRENT_SC->SCp.this_residual =
+                     CURRENT_SC->SCp.buffer->length;
                  } 
              }
  
@@ -2028,15 +2099,15 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
              {
                printk("aha152x: more data than expected (%d bytes)\n",
                       GETPORT(FIFOSTAT));
-               SETBITS(DMACNTRL0, _8BIT );
-               printk("aha152x: data ( ");
+               SETBITS(DMACNTRL0, _8BIT);
+               printk("aha152x: data (");
                while(fifodata--)
-                 printk("%2x ", GETPORT( DATAPORT ));
+                 printk("%2x ", GETPORT(DATAPORT));
                printk(")\n");
              }
 
 #if defined(DEBUG_DATAI)
-           if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
              if(!fifodata)
                printk("fifo empty, ");
              else
@@ -2045,23 +2116,25 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
          }
 
 #if defined(DEBUG_DATAI)
-       if((aha152x_debug & debug_datai) && (current_SC->SCp.buffers_residual || current_SC->SCp.this_residual))
+        if((HOSTDATA(shpnt)->debug & debug_datai) &&
+           (CURRENT_SC->SCp.buffers_residual ||
+            CURRENT_SC->SCp.this_residual))
          printk("left buffers (buffers=%d, bytes=%d), ",
-                current_SC->SCp.buffers_residual, 
-                current_SC->SCp.this_residual);
+                CURRENT_SC->SCp.buffers_residual, 
+                CURRENT_SC->SCp.this_residual);
 #endif
        /* transfer can be considered ended, when SCSIEN reads back zero */
        CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-       while( TESTHI( SXFRCTL0, SCSIEN ) )
+        while(TESTHI(SXFRCTL0, SCSIEN))
          ;
-       CLRBITS(DMACNTRL0, ENDMA );
+        CLRBITS(DMACNTRL0, ENDMA);
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
-       if(aha152x_debug & (debug_datai|debug_intr))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr))
          printk("got %d bytes, ", GETSTCNT());
 #endif
 
-       current_SC->SCp.have_data_in++;
+        CURRENT_SC->SCp.have_data_in++;
       }
       break;
 
@@ -2070,95 +2143,96 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
        int data_count;
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-       if(aha152x_debug & (debug_datao|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases))
          printk("DATA OUT, ");
 #endif
 #if defined(DEBUG_DATAO)
-       if(aha152x_debug & debug_datao)
+        if(HOSTDATA(shpnt)->debug & debug_datao)
          printk("got data to send (bytes=%d, buffers=%d), ",
-                current_SC->SCp.this_residual,
-                current_SC->SCp.buffers_residual );
+                CURRENT_SC->SCp.this_residual,
+                CURRENT_SC->SCp.buffers_residual);
 #endif
 
-       if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) )
+        if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
          {
-           printk("%d(%d) left in FIFO, ", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT) );
-           aha152x_panic("FIFO should be empty");
+            printk("%d(%d) left in FIFO, ",
+                  GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+            aha152x_panic(shpnt, "FIFO should be empty");
          }
 
+        SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1);
+        SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
+        
        SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
        SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
 
-       SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
-       SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
-       SETPORT( SIMODE0, 0 );
-       SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 
        /* while current buffer is not empty or
           there are more buffers to transfer */
-       while( TESTLO( SSTAT1, PHASEMIS ) &&
-                (current_SC->SCp.this_residual ||
-                 current_SC->SCp.buffers_residual) )
+        while(TESTLO(SSTAT1, PHASEMIS) &&
+              (CURRENT_SC->SCp.this_residual ||
+               CURRENT_SC->SCp.buffers_residual))
          {
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
              printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
-                    current_SC->SCp.this_residual,
-                    current_SC->SCp.buffers_residual);
+                    CURRENT_SC->SCp.this_residual,
+                    CURRENT_SC->SCp.buffers_residual);
 #endif
            /* transfer rest of buffer, but max. 128 byte */
-           data_count = current_SC->SCp.this_residual > 128 ?
-                        128 : current_SC->SCp.this_residual ;
+            data_count =
+              CURRENT_SC->SCp.this_residual > 128 ?
+              128 : CURRENT_SC->SCp.this_residual ;
 
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
              printk("data_count=%d, ", data_count);
 #endif
   
            if(data_count&1)
              {
                /* put a single byte in byte mode */
-               SETBITS(DMACNTRL0, _8BIT );
-               SETPORT(DATAPORT, *current_SC->SCp.ptr++);
-               current_SC->SCp.this_residual--;
+               SETBITS(DMACNTRL0, _8BIT);
+               SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
+               CURRENT_SC->SCp.this_residual--;
              }
            if(data_count>1)
              {
-               CLRBITS(DMACNTRL0, _8BIT );
-               data_count >>= 1; /* Number of words */
-               outsw( DATAPORT, current_SC->SCp.ptr, data_count );
-               current_SC->SCp.ptr           += 2 * data_count;
-               current_SC->SCp.this_residual -= 2 * data_count;
+               CLRBITS(DMACNTRL0, _8BIT);
+               data_count >>= 1; /* number of words */
+               outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
+               CURRENT_SC->SCp.ptr           += 2 * data_count;
+               CURRENT_SC->SCp.this_residual -= 2 * data_count;
              }
 
            /* wait for FIFO to get empty */
-           while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
+            while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT))
              ;
 
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
              printk("fifo (%d bytes), transfered (%d bytes), ",
-                    GETPORT(FIFOSTAT), GETSTCNT() );
+                    GETPORT(FIFOSTAT), GETSTCNT());
 #endif
 
            /* if this buffer is empty and there are more buffers left */
-           if ( TESTLO( SSTAT1, PHASEMIS ) &&
-                !current_SC->SCp.this_residual &&
-                 current_SC->SCp.buffers_residual)
+            if (TESTLO(SSTAT1, PHASEMIS) &&
+               !CURRENT_SC->SCp.this_residual &&
+               CURRENT_SC->SCp.buffers_residual)
              {
                 /* advance to next buffer */
-                current_SC->SCp.buffers_residual--;
-                current_SC->SCp.buffer++;
-                current_SC->SCp.ptr =
-                  current_SC->SCp.buffer->address;
-                current_SC->SCp.this_residual =
-                current_SC->SCp.buffer->length;
+               CURRENT_SC->SCp.buffers_residual--;
+               CURRENT_SC->SCp.buffer++;
+               CURRENT_SC->SCp.ptr =
+                 CURRENT_SC->SCp.buffer->address;
+               CURRENT_SC->SCp.this_residual =
+                 CURRENT_SC->SCp.buffer->length;
              }
          }
 
-       if ( current_SC->SCp.this_residual ||
-            current_SC->SCp.buffers_residual )
+        if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual)
          {
            /* target leaves DATA OUT for an other phase
               (perhaps disconnect) */
@@ -2167,46 +2241,47 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
            data_count = GETPORT(SSTAT2) & (SFULL|SFCNT);
 
            data_count += GETPORT(FIFOSTAT) ;
-           current_SC->SCp.ptr           -= data_count;
-           current_SC->SCp.this_residual += data_count;
+            CURRENT_SC->SCp.ptr           -= data_count;
+            CURRENT_SC->SCp.this_residual += data_count;
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
-             printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), transfer incomplete, resetting fifo, ",
-                    current_SC->SCp.this_residual,
-                    current_SC->SCp.buffers_residual,
-                    data_count );
+            if(HOSTDATA(shpnt)->debug & debug_datao)
+              printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), "
+                    "transfer incomplete, resetting fifo, ",
+                    CURRENT_SC->SCp.this_residual,
+                    CURRENT_SC->SCp.buffers_residual,
+                    data_count);
 #endif
            SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-           CLRBITS(SXFRCTL0, SCSIEN|DMAEN );
+            CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
            CLRBITS(DMACNTRL0, ENDMA);
          }
        else
          {
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
              printk("waiting for SCSI fifo to get empty, ");
 #endif
            /* wait for SCSI fifo to get empty */
-           while( TESTLO( SSTAT2, SEMPTY ) )
+            while(TESTLO(SSTAT2, SEMPTY))
              ;
 #if defined(DEBUG_DATAO)
-           if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
              printk("ok, left data (bytes=%d, buffers=%d) ",
-                    current_SC->SCp.this_residual,
-                    current_SC->SCp.buffers_residual);
+                    CURRENT_SC->SCp.this_residual,
+                    CURRENT_SC->SCp.buffers_residual);
 #endif
            CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
 
            /* transfer can be considered ended, when SCSIEN reads back zero */
-           while( TESTHI( SXFRCTL0, SCSIEN ) )
+            while(TESTHI(SXFRCTL0, SCSIEN))
              ;
 
            CLRBITS(DMACNTRL0, ENDMA);
          }
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR)
-       if(aha152x_debug & (debug_datao|debug_intr))
-         printk("sent %d data bytes, ", GETSTCNT() );
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr))
+          printk("sent %d data bytes, ", GETSTCNT());
 #endif
       }
       break;
@@ -2216,12 +2291,12 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
       leave_driver("(BUSFREE) intr");
 #endif
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
        printk("unexpected BUS FREE, ");
 #endif
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      aha152x_done( DID_ERROR << 16 );               /* Don't know any better */
+      aha152x_done(shpnt, DID_ERROR << 16);         /* Don't know any better */
       return;
       break;
 
@@ -2231,10 +2306,10 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
 #endif
       printk("PARITY error in DATA phase, ");
 
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      SETBITS( DMACNTRL0, INTEN );
-      aha152x_done( DID_PARITY << 16 );
+      SETBITS(DMACNTRL0, INTEN);
+      aha152x_done(shpnt, DID_PARITY << 16);
       return;
       break;
 
@@ -2246,85 +2321,86 @@ void aha152x_intr( int irqno, struct pt_regs * regs )
   if(done)
     {
 #if defined(DEBUG_INTR)
-      if(aha152x_debug & debug_intr)
+      if(HOSTDATA(shpnt)->debug & debug_intr)
        printk("command done.\n");
 #endif
 #if defined(DEBUG_RACE)
       leave_driver("(done) intr");
 #endif
 
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-      SETPORT(SCSISEQ, disconnected_SC ? ENRESELI : 0 );
-
-      SETBITS( DMACNTRL0, INTEN );
-
-      aha152x_done(   (current_SC->SCp.Status  & 0xff)
-                   | ( (current_SC->SCp.Message & 0xff) << 8)
-                   | ( DID_OK << 16) );
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+      SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
+      
+      SETBITS(DMACNTRL0, INTEN);
+      
+      aha152x_done(shpnt,
+                  (CURRENT_SC->SCp.Status  & 0xff)
+                  | ((CURRENT_SC->SCp.Message & 0xff) << 8)
+                  | (DID_OK << 16));
 
 #if defined(DEBUG_RACE)
       printk("done returned (DID_OK: Status=%x; Message=%x).\n",
-            current_SC->SCp.Status, current_SC->SCp.Message);
+             CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message);
 #endif
       return;
     }
 
-  if(current_SC)
-    current_SC->SCp.phase |= 1<<16 ;
+  if(CURRENT_SC)
+    CURRENT_SC->SCp.phase |= 1<<16 ;
 
-  SETPORT( SIMODE0, 0 );
-  SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+  SETPORT(SIMODE0, 0);
+  SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_enintr();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_enintr(shpnt);
 #endif
 #if defined(DEBUG_RACE)
   leave_driver("(PHASEEND) intr");
 #endif
 
-  SETBITS( DMACNTRL0, INTEN);
+  SETBITS(DMACNTRL0, INTEN);
   return;
 }
 
 /* 
  * Dump the current driver status and panic...
  */
-static void aha152x_panic(const char *msg)
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg)
 {
-  printk("\naha152x_panic: %s\n", msg);
-  show_queues();
+  printk("\naha152x: %s\n", msg);
+  show_queues(shpnt);
   panic("aha152x panic");
 }
 
 /*
  * Display registers of AIC-6260
  */
-static void disp_ports(void)
+static void disp_ports(struct Scsi_Host *shpnt)
 {
 #ifdef DEBUG_AHA152X
   int s;
 
 #ifdef SKIP_PORTS
-  if(aha152x_debug & debug_skipports)
+  if(HOSTDATA(shpnt)->debug & debug_skipports)
        return;
 #endif
 
-  printk("\n%s: ", current_SC ? "on bus" : "waiting");
+  printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
 
   s=GETPORT(SCSISEQ);
-  printk("SCSISEQ ( ");
-  if( s & TEMODEO )     printk("TARGET MODE ");
-  if( s & ENSELO )      printk("SELO ");
-  if( s & ENSELI )      printk("SELI ");
-  if( s & ENRESELI )    printk("RESELI ");
-  if( s & ENAUTOATNO )  printk("AUTOATNO ");
-  if( s & ENAUTOATNI )  printk("AUTOATNI ");
-  if( s & ENAUTOATNP )  printk("AUTOATNP ");
-  if( s & SCSIRSTO )    printk("SCSIRSTO ");
+  printk("SCSISEQ (");
+  if(s & TEMODEO)     printk("TARGET MODE ");
+  if(s & ENSELO)      printk("SELO ");
+  if(s & ENSELI)      printk("SELI ");
+  if(s & ENRESELI)    printk("RESELI ");
+  if(s & ENAUTOATNO)  printk("AUTOATNO ");
+  if(s & ENAUTOATNI)  printk("AUTOATNI ");
+  if(s & ENAUTOATNP)  printk("AUTOATNP ");
+  if(s & SCSIRSTO)    printk("SCSIRSTO ");
   printk(");");
 
-  printk(" SCSISIG ( ");
+  printk(" SCSISIG (");
   s=GETPORT(SCSISIG);
   switch(s & P_MASK)
     {
@@ -2351,132 +2427,131 @@ static void disp_ports(void)
       break;
     }
   
-  printk(" ); ");
+  printk("); ");
 
-  printk("INTSTAT ( %s ); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
+  printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
 
-  printk("SSTAT ( ");
+  printk("SSTAT (");
   s=GETPORT(SSTAT0);
-  if( s & TARGET )   printk("TARGET ");
-  if( s & SELDO )    printk("SELDO ");
-  if( s & SELDI )    printk("SELDI ");
-  if( s & SELINGO )  printk("SELINGO ");
-  if( s & SWRAP )    printk("SWRAP ");
-  if( s & SDONE )    printk("SDONE ");
-  if( s & SPIORDY )  printk("SPIORDY ");
-  if( s & DMADONE )  printk("DMADONE ");
+  if(s & TARGET)   printk("TARGET ");
+  if(s & SELDO)    printk("SELDO ");
+  if(s & SELDI)    printk("SELDI ");
+  if(s & SELINGO)  printk("SELINGO ");
+  if(s & SWRAP)    printk("SWRAP ");
+  if(s & SDONE)    printk("SDONE ");
+  if(s & SPIORDY)  printk("SPIORDY ");
+  if(s & DMADONE)  printk("DMADONE ");
 
   s=GETPORT(SSTAT1);
-  if( s & SELTO )     printk("SELTO ");
-  if( s & ATNTARG )   printk("ATNTARG ");
-  if( s & SCSIRSTI )  printk("SCSIRSTI ");
-  if( s & PHASEMIS )  printk("PHASEMIS ");
-  if( s & BUSFREE )   printk("BUSFREE ");
-  if( s & SCSIPERR )  printk("SCSIPERR ");
-  if( s & PHASECHG )  printk("PHASECHG ");
-  if( s & REQINIT )   printk("REQINIT ");
+  if(s & SELTO)     printk("SELTO ");
+  if(s & ATNTARG)   printk("ATNTARG ");
+  if(s & SCSIRSTI)  printk("SCSIRSTI ");
+  if(s & PHASEMIS)  printk("PHASEMIS ");
+  if(s & BUSFREE)   printk("BUSFREE ");
+  if(s & SCSIPERR)  printk("SCSIPERR ");
+  if(s & PHASECHG)  printk("PHASECHG ");
+  if(s & REQINIT)   printk("REQINIT ");
   printk("); ");
 
 
-  printk("SSTAT ( ");
+  printk("SSTAT (");
 
   s=GETPORT(SSTAT0) & GETPORT(SIMODE0);
 
-  if( s & TARGET )    printk("TARGET ");
-  if( s & SELDO )     printk("SELDO ");
-  if( s & SELDI )     printk("SELDI ");
-  if( s & SELINGO )   printk("SELINGO ");
-  if( s & SWRAP )     printk("SWRAP ");
-  if( s & SDONE )     printk("SDONE ");
-  if( s & SPIORDY )   printk("SPIORDY ");
-  if( s & DMADONE )   printk("DMADONE ");
+  if(s & TARGET)    printk("TARGET ");
+  if(s & SELDO)     printk("SELDO ");
+  if(s & SELDI)     printk("SELDI ");
+  if(s & SELINGO)   printk("SELINGO ");
+  if(s & SWRAP)     printk("SWRAP ");
+  if(s & SDONE)     printk("SDONE ");
+  if(s & SPIORDY)   printk("SPIORDY ");
+  if(s & DMADONE)   printk("DMADONE ");
 
   s=GETPORT(SSTAT1) & GETPORT(SIMODE1);
 
-  if( s & SELTO )     printk("SELTO ");
-  if( s & ATNTARG )   printk("ATNTARG ");
-  if( s & SCSIRSTI )  printk("SCSIRSTI ");
-  if( s & PHASEMIS )  printk("PHASEMIS ");
-  if( s & BUSFREE )   printk("BUSFREE ");
-  if( s & SCSIPERR )  printk("SCSIPERR ");
-  if( s & PHASECHG )  printk("PHASECHG ");
-  if( s & REQINIT )   printk("REQINIT ");
+  if(s & SELTO)     printk("SELTO ");
+  if(s & ATNTARG)   printk("ATNTARG ");
+  if(s & SCSIRSTI)  printk("SCSIRSTI ");
+  if(s & PHASEMIS)  printk("PHASEMIS ");
+  if(s & BUSFREE)   printk("BUSFREE ");
+  if(s & SCSIPERR)  printk("SCSIPERR ");
+  if(s & PHASECHG)  printk("PHASECHG ");
+  if(s & REQINIT)   printk("REQINIT ");
   printk("); ");
 
-  printk("SXFRCTL0 ( ");
+  printk("SXFRCTL0 (");
 
   s=GETPORT(SXFRCTL0);
-  if( s & SCSIEN )    printk("SCSIEN ");
-  if( s & DMAEN )     printk("DMAEN ");
-  if( s & CH1 )       printk("CH1 ");
-  if( s & CLRSTCNT )  printk("CLRSTCNT ");
-  if( s & SPIOEN )    printk("SPIOEN ");
-  if( s & CLRCH1 )    printk("CLRCH1 ");
+  if(s & SCSIEN)    printk("SCSIEN ");
+  if(s & DMAEN)     printk("DMAEN ");
+  if(s & CH1)       printk("CH1 ");
+  if(s & CLRSTCNT)  printk("CLRSTCNT ");
+  if(s & SPIOEN)    printk("SPIOEN ");
+  if(s & CLRCH1)    printk("CLRCH1 ");
   printk("); ");
 
-  printk("SIGNAL ( ");
+  printk("SIGNAL (");
 
   s=GETPORT(SCSISIG);
-  if( s & ATNI )  printk("ATNI ");
-  if( s & SELI )  printk("SELI ");
-  if( s & BSYI )  printk("BSYI ");
-  if( s & REQI )  printk("REQI ");
-  if( s & ACKI )  printk("ACKI ");
+  if(s & ATNI)  printk("ATNI ");
+  if(s & SELI)  printk("SELI ");
+  if(s & BSYI)  printk("BSYI ");
+  if(s & REQI)  printk("REQI ");
+  if(s & ACKI)  printk("ACKI ");
   printk("); ");
 
-  printk("SELID ( %02x ), ", GETPORT(SELID) );
+  printk("SELID (%02x), ", GETPORT(SELID));
 
-  printk("SSTAT2 ( ");
+  printk("SSTAT2 (");
 
   s=GETPORT(SSTAT2);
-  if( s & SOFFSET)  printk("SOFFSET ");
-  if( s & SEMPTY)   printk("SEMPTY ");
-  if( s & SFULL)    printk("SFULL ");
-  printk("); SFCNT ( %d ); ", s & (SFULL|SFCNT) );
+  if(s & SOFFSET)  printk("SOFFSET ");
+  if(s & SEMPTY)   printk("SEMPTY ");
+  if(s & SFULL)    printk("SFULL ");
+  printk("); SFCNT (%d); ", s & (SFULL|SFCNT));
 
-#if 0
-  printk("SSTAT4 ( ");
+  s=GETPORT(SSTAT3);
+  printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f);
+  
+  printk("SSTAT4 (");
   s=GETPORT(SSTAT4);
-  if( s & SYNCERR)   printk("SYNCERR ");
-  if( s & FWERR)     printk("FWERR ");
-  if( s & FRERR)     printk("FRERR ");
+  if(s & SYNCERR)   printk("SYNCERR ");
+  if(s & FWERR)     printk("FWERR ");
+  if(s & FRERR)     printk("FRERR ");
   printk("); ");
-#endif
-
-  printk("FCNT ( %d ); ", GETPORT(FIFOSTAT) );
 
-  printk("DMACNTRL0 ( ");
+  printk("DMACNTRL0 (");
   s=GETPORT(DMACNTRL0);
-  printk( "%s ", s & _8BIT      ? "8BIT"  : "16BIT" );
-  printk( "%s ", s & DMA        ? "DMA"   : "PIO"   );
-  printk( "%s ", s & WRITE_READ ? "WRITE" : "READ"  );
-  if( s & ENDMA )    printk("ENDMA ");
-  if( s & INTEN )    printk("INTEN ");
-  if( s & RSTFIFO )  printk("RSTFIFO ");
-  if( s & SWINT )    printk("SWINT ");
+  printk("%s ", s & _8BIT      ? "8BIT"  : "16BIT");
+  printk("%s ", s & DMA        ? "DMA"   : "PIO"  );
+  printk("%s ", s & WRITE_READ ? "WRITE" : "READ" );
+  if(s & ENDMA)    printk("ENDMA ");
+  if(s & INTEN)    printk("INTEN ");
+  if(s & RSTFIFO)  printk("RSTFIFO ");
+  if(s & SWINT)    printk("SWINT ");
   printk("); ");
 
 
 #if 0
-  printk("DMACNTRL1 ( ");
+  printk("DMACNTRL1 (");
 
   s=GETPORT(DMACNTRL1);
-  if( s & PWRDWN )    printk("PWRDN ");
+  if(s & PWRDWN)    printk("PWRDN ");
   printk("); ");
 
 
-  printk("STK ( %d ); ", s & 0xf);
+  printk("STK (%d); ", s & 0xf);
+  
+#endif
 
   printk("DMASTAT (");
   s=GETPORT(DMASTAT);
-  if( s & ATDONE )     printk("ATDONE ");
-  if( s & WORDRDY )    printk("WORDRDY ");
-  if( s & DFIFOFULL )  printk("DFIFOFULL ");
-  if( s & DFIFOEMP )   printk("DFIFOEMP ");
+  if(s & ATDONE)     printk("ATDONE ");
+  if(s & WORDRDY)    printk("WORDRDY ");
+  if(s & DFIFOFULL)  printk("DFIFOFULL ");
+  if(s & DFIFOEMP)   printk("DFIFOEMP ");
   printk(")");
 
-#endif
-
   printk("\n");
 #endif
 }
@@ -2484,29 +2559,29 @@ static void disp_ports(void)
 /*
  * display enabled interrupts
  */
-static void disp_enintr(void)
+static void disp_enintr(struct Scsi_Host *shpnt)
 {
   int s;
 
-  printk("enabled interrupts ( ");
+  printk("enabled interrupts (");
   
   s=GETPORT(SIMODE0);
-  if( s & ENSELDO )    printk("ENSELDO ");
-  if( s & ENSELDI )    printk("ENSELDI ");
-  if( s & ENSELINGO )  printk("ENSELINGO ");
-  if( s & ENSWRAP )    printk("ENSWRAP ");
-  if( s & ENSDONE )    printk("ENSDONE ");
-  if( s & ENSPIORDY )  printk("ENSPIORDY ");
-  if( s & ENDMADONE )  printk("ENDMADONE ");
+  if(s & ENSELDO)    printk("ENSELDO ");
+  if(s & ENSELDI)    printk("ENSELDI ");
+  if(s & ENSELINGO)  printk("ENSELINGO ");
+  if(s & ENSWRAP)    printk("ENSWRAP ");
+  if(s & ENSDONE)    printk("ENSDONE ");
+  if(s & ENSPIORDY)  printk("ENSPIORDY ");
+  if(s & ENDMADONE)  printk("ENDMADONE ");
 
   s=GETPORT(SIMODE1);
-  if( s & ENSELTIMO )    printk("ENSELTIMO ");
-  if( s & ENATNTARG )    printk("ENATNTARG ");
-  if( s & ENPHASEMIS )   printk("ENPHASEMIS ");
-  if( s & ENBUSFREE )    printk("ENBUSFREE ");
-  if( s & ENSCSIPERR )   printk("ENSCSIPERR ");
-  if( s & ENPHASECHG )   printk("ENPHASECHG ");
-  if( s & ENREQINIT )    printk("ENREQINIT ");
+  if(s & ENSELTIMO)    printk("ENSELTIMO ");
+  if(s & ENATNTARG)    printk("ENATNTARG ");
+  if(s & ENPHASEMIS)   printk("ENPHASEMIS ");
+  if(s & ENBUSFREE)    printk("ENBUSFREE ");
+  if(s & ENSCSIPERR)   printk("ENSCSIPERR ");
+  if(s & ENPHASECHG)   printk("ENPHASECHG ");
+  if(s & ENREQINIT)    printk("ENREQINIT ");
   printk(")\n");
 }
 
@@ -2560,7 +2635,7 @@ static void leave_driver(const char *func)
  */
 static void show_command(Scsi_Cmnd *ptr)
 {
-  printk("0x%08x: target=%d; lun=%d; cmnd=( ",
+  printk("0x%08x: target=%d; lun=%d; cmnd=(",
         (unsigned int) ptr, ptr->target, ptr->lun);
   
   print_command(ptr->cmnd);
@@ -2568,15 +2643,15 @@ static void show_command(Scsi_Cmnd *ptr)
   printk("); residual=%d; buffers=%d; phase |",
         ptr->SCp.this_residual, ptr->SCp.buffers_residual);
 
-  if( ptr->SCp.phase & not_issued   )  printk("not issued|");
-  if( ptr->SCp.phase & in_selection )  printk("in selection|");
-  if( ptr->SCp.phase & disconnected )  printk("disconnected|");
-  if( ptr->SCp.phase & aborted      )  printk("aborted|");
-  if( ptr->SCp.phase & sent_ident   )  printk("send_ident|");
-  if( ptr->SCp.phase & in_other )
+  if(ptr->SCp.phase & not_issued  )  printk("not issued|");
+  if(ptr->SCp.phase & in_selection)  printk("in selection|");
+  if(ptr->SCp.phase & disconnected)  printk("disconnected|");
+  if(ptr->SCp.phase & aborted     )  printk("aborted|");
+  if(ptr->SCp.phase & sent_ident  )  printk("send_ident|");
+  if(ptr->SCp.phase & in_other)
     { 
       printk("; in other(");
-      switch( (ptr->SCp.phase >> 16) & P_MASK )
+      switch((ptr->SCp.phase >> 16) & P_MASK)
        {
        case P_DATAO:
          printk("DATA OUT");
@@ -2610,7 +2685,7 @@ static void show_command(Scsi_Cmnd *ptr)
 /*
  * Dump the queued data
  */
-static void show_queues(void)
+static void show_queues(struct Scsi_Host *shpnt)
 {
   unsigned long flags;
   Scsi_Cmnd *ptr;
@@ -2618,24 +2693,243 @@ static void show_queues(void)
   save_flags(flags);
   cli();
   printk("QUEUE STATUS:\nissue_SC:\n");
-  for(ptr=issue_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
+  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
     show_command(ptr);
 
   printk("current_SC:\n");
-  if(current_SC)
-    show_command(current_SC);
+  if(CURRENT_SC)
+    show_command(CURRENT_SC);
   else
     printk("none\n");
 
   printk("disconnected_SC:\n");
-  for(ptr=disconnected_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
     show_command(ptr);
 
-  disp_ports();
-  disp_enintr();
+  disp_ports(shpnt);
+  disp_enintr(shpnt);
   restore_flags(flags);
 }
 
+int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+{
+  return(-ENOSYS);  /* Currently this is a no-op */
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) pos += sprintf(pos, ## args)
+
+static int get_command(char *pos, Scsi_Cmnd *ptr)
+{
+  char *start = pos;
+  int i;
+  
+  SPRINTF("0x%08x: target=%d; lun=%d; cmnd=(",
+          (unsigned int) ptr, ptr->target, ptr->lun);
+  
+  for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++)
+    SPRINTF("0x%02x", ptr->cmnd[i]);
+  
+  SPRINTF("); residual=%d; buffers=%d; phase |",
+          ptr->SCp.this_residual, ptr->SCp.buffers_residual);
+  
+  if(ptr->SCp.phase & not_issued  )  SPRINTF("not issued|");
+  if(ptr->SCp.phase & in_selection)  SPRINTF("in selection|");
+  if(ptr->SCp.phase & disconnected)  SPRINTF("disconnected|");
+  if(ptr->SCp.phase & aborted     )  SPRINTF("aborted|");
+  if(ptr->SCp.phase & sent_ident  )  SPRINTF("send_ident|");
+  if(ptr->SCp.phase & in_other)
+    { 
+      SPRINTF("; in other(");
+      switch((ptr->SCp.phase >> 16) & P_MASK)
+        {
+        case P_DATAO:
+          SPRINTF("DATA OUT");
+          break;
+        case P_DATAI:
+          SPRINTF("DATA IN");
+          break;
+        case P_CMD:
+          SPRINTF("COMMAND");
+          break;
+        case P_STATUS:
+          SPRINTF("STATUS");
+          break;
+        case P_MSGO:
+          SPRINTF("MESSAGE OUT");
+          break;
+        case P_MSGI:
+          SPRINTF("MESSAGE IN");
+          break;
+        default: 
+          SPRINTF("*illegal*");
+          break;
+        }
+      SPRINTF(")");
+      if(ptr->SCp.phase & (1<<16))
+        SPRINTF("; phaseend");
+    }
+  SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
+  
+  return(pos-start);
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
+
+int aha152x_proc_info(
+                     char *buffer,
+                     char **start,
+                     off_t offset,
+                     int length,
+                     int hostno,
+                     int inout
+                     )
+{
+  int i;
+  char *pos = buffer;
+  Scsi_Device *scd;
+  struct Scsi_Host *shpnt;
+  unsigned long flags;
+  Scsi_Cmnd *ptr;
+  
+  for(i=0, shpnt= (struct Scsi_Host *) NULL; i<IRQS; i++)
+    if(aha152x_host[i] && aha152x_host[i]->host_no == hostno)
+      shpnt=aha152x_host[i];
+  
+  if(!shpnt)
+    return(-ESRCH);
+  
+  if(inout) /* Has data been written to the file ? */ 
+    return(aha152x_set_info(buffer, length, shpnt));
+  
+  SPRINTF(AHA152X_REVID "\n");
+  
+  save_flags(flags);
+  cli();
+  
+  SPRINTF("vital data:\nioports 0x%04x to 0x%04x\n",
+          shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1);
+  SPRINTF("interrupt 0x%02x\n", shpnt->irq);
+  SPRINTF("disconnection/reconnection %s\n", 
+          HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled");
+  SPRINTF("parity checking %s\n", 
+          HOSTDATA(shpnt)->parity ? "enabled" : "disabled");
+  SPRINTF("synchronous transfers %s\n", 
+          HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
+  SPRINTF("current queued %d commands\n",
+          HOSTDATA(shpnt)->commands);
+  
+#if 0
+  SPRINTF("synchronously operating targets (tick=%ld ns):\n",
+          250000000/loops_per_sec);
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+                      (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*
+                        250000000/loops_per_sec,
+                      HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#else
+  SPRINTF("synchronously operating targets (tick=50 ns):\n");
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50,
+              HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#endif
+  
+#ifdef DEBUG_AHA152X
+#define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
+  
+  SPRINTF("enabled debugging options:\n");
+  
+  PDEBUG(debug_skipports, "skip ports");
+  PDEBUG(debug_queue, "queue");
+  PDEBUG(debug_intr, "interrupt");
+  PDEBUG(debug_selection, "selection");
+  PDEBUG(debug_msgo, "message out");
+  PDEBUG(debug_msgi, "message in");
+  PDEBUG(debug_status, "status");
+  PDEBUG(debug_cmd, "command");
+  PDEBUG(debug_datai, "data in");
+  PDEBUG(debug_datao, "data out");
+  PDEBUG(debug_abort, "abort");
+  PDEBUG(debug_done, "done");
+  PDEBUG(debug_biosparam, "bios parameters");
+  PDEBUG(debug_phases, "phases");
+  PDEBUG(debug_queues, "queues");
+  PDEBUG(debug_reset, "reset");
+  
+  SPRINTF("\n");
+#endif
+  
+  SPRINTF("queue status:\nnot yet issued commands:\n");
+  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
+  if(CURRENT_SC)
+    {
+      SPRINTF("current command:\n");
+      pos += get_command(pos, CURRENT_SC);
+    }
+  
+  SPRINTF("disconnected commands:\n");
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
+  restore_flags(flags);
+  
+  scd = scsi_devices;
+  
+  SPRINTF("Attached devices: %s\n", (scd)?"":"none");
+  
+  while (scd) {
+    if (scd->host == shpnt) {
+      
+      SPRINTF("Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
+              scd->channel, scd->id, scd->lun);
+      for (i=0; i<8; i++) {
+        if (scd->vendor[i] >= 0x20)
+          SPRINTF("%c", scd->vendor[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Model: ");
+      for (i = 0; i < 16; i++) {
+        if (scd->model[i] >= 0x20)
+          SPRINTF("%c", scd->model[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Rev: ");
+      for (i = 0; i < 4; i++) {
+        if (scd->rev[i] >= 0x20)
+          SPRINTF("%c", scd->rev[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF("\n");
+      
+      SPRINTF("  Type:   %d ", scd->type);
+      SPRINTF("               ANSI SCSI revision: %02x",
+              (scd->scsi_level < 3)?1:2);
+      
+      if (scd->scsi_level == 2)
+        SPRINTF(" CCS\n");
+      else
+        SPRINTF("\n");
+    }
+    scd = scd->next;
+  }
+  
+  *start=buffer;
+  return (pos-buffer < length ? pos-buffer : length);     
+}
+
 #ifdef MODULE
 /* Eventually this will go into an include file, but this will be later */
 Scsi_Host_Template driver_template = AHA152X;
index 7a7890032e091cdbc0714d644c581bab0398e590..be1f4995e3a8752084ff5db4500073a8268704c4 100644 (file)
@@ -2,7 +2,7 @@
 #define _AHA152X_H
 
 /*
- * $Id: aha152x.h,v 1.9 1995/03/18 09:21:04 root Exp root $
+ * $Id: aha152x.h,v 1.11 1995/12/07 01:03:20 fischer Exp root $
  */
 
 #if defined(__KERNEL__)
@@ -17,20 +17,21 @@ int        aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int        aha152x_abort(Scsi_Cmnd *);
 int        aha152x_reset(Scsi_Cmnd *);
 int        aha152x_biosparam(Disk *, kdev_t, int*);
+int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
 
 /* number of queueable commands
    (unless we support more than 1 cmd_per_lun this should do) */
 #define AHA152X_MAXQUEUE       7               
 
-#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.9 $"
+#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.11 $"
 
 extern struct proc_dir_entry proc_scsi_aha152x;
 
 /* Initial value of Scsi_Host entry */
 #define AHA152X       { /* next */             NULL,                       \
                        /* usage_count */       NULL,                       \
-                                               &proc_scsi_aha152x,         \
-                                               NULL,                       \
+                       /* proc_dir */          &proc_scsi_aha152x,         \
+                       /* proc_info */         aha152x_proc_info,          \
                        /* name */              AHA152X_REVID,              \
                        /* detect */            aha152x_detect,             \
                        /* release */           NULL,                       \
@@ -52,37 +53,44 @@ extern struct proc_dir_entry proc_scsi_aha152x;
 
 
 /* port addresses */
-#define SCSISEQ                (port_base+0x00)        /* SCSI sequence control */
-#define SXFRCTL0       (port_base+0x01)        /* SCSI transfer control 0 */
-#define SXFRCTL1       (port_base+0x02)        /* SCSI transfer control 1 */
-#define SCSISIG                (port_base+0x03)        /* SCSI signal in/out */
-#define SCSIRATE       (port_base+0x04)        /* SCSI rate control */
-#define SELID          (port_base+0x05)        /* selection/reselection ID */
+#define SCSISEQ                (shpnt->io_port+0x00)   /* SCSI sequence control */
+#define SXFRCTL0       (shpnt->io_port+0x01)   /* SCSI transfer control 0 */
+#define SXFRCTL1       (shpnt->io_port+0x02)   /* SCSI transfer control 1 */
+#define SCSISIG                (shpnt->io_port+0x03)   /* SCSI signal in/out */
+#define SCSIRATE       (shpnt->io_port+0x04)   /* SCSI rate control */
+#define SELID          (shpnt->io_port+0x05)   /* selection/reselection ID */
 #define SCSIID         SELID                   /* SCSI ID */
-#define SCSIDAT                (port_base+0x06)        /* SCSI latched data */
-#define SCSIBUS                (port_base+0x07)        /* SCSI data bus */
-#define STCNT0         (port_base+0x08)        /* SCSI transfer count 0 */
-#define STCNT1         (port_base+0x09)        /* SCSI transfer count 1 */
-#define STCNT2         (port_base+0x0a)        /* SCSI transfer count 2 */
-#define SSTAT0         (port_base+0x0b)        /* SCSI interrupt status 0 */
-#define SSTAT1         (port_base+0x0c)        /* SCSI interrupt status 1 */
-#define SSTAT2         (port_base+0x0d)        /* SCSI interrupt status 2 */
-#define SCSITEST       (port_base+0x0e)        /* SCSI test control */
-#define SSTAT4         (port_base+0x0f)        /* SCSI status 4 */
-#define SIMODE0                (port_base+0x10)        /* SCSI interrupt mode 0 */
-#define SIMODE1                (port_base+0x11)        /* SCSI interrupt mode 1 */
-#define DMACNTRL0      (port_base+0x12)        /* DMA control 0 */
-#define DMACNTRL1      (port_base+0x13)        /* DMA control 1 */
-#define DMASTAT                (port_base+0x14)        /* DMA status */
-#define FIFOSTAT       (port_base+0x15)        /* FIFO status */
-#define DATAPORT       (port_base+0x16)        /* DATA port */
-#define BRSTCNTRL      (port_base+0x18)        /* burst control */
-#define PORTA          (port_base+0x1a)        /* PORT A */
-#define PORTB          (port_base+0x1b)        /* PORT B */
-#define REV            (port_base+0x1c)        /* revision */
-#define STACK          (port_base+0x1d)        /* stack */
-#define TEST           (port_base+0x1e)        /* test register */
-
+#define SCSIDAT                (shpnt->io_port+0x06)   /* SCSI latched data */
+#define SCSIBUS                (shpnt->io_port+0x07)   /* SCSI data bus */
+#define STCNT0         (shpnt->io_port+0x08)   /* SCSI transfer count 0 */
+#define STCNT1         (shpnt->io_port+0x09)   /* SCSI transfer count 1 */
+#define STCNT2         (shpnt->io_port+0x0a)   /* SCSI transfer count 2 */
+#define SSTAT0         (shpnt->io_port+0x0b)   /* SCSI interrupt status 0 */
+#define SSTAT1         (shpnt->io_port+0x0c)   /* SCSI interrupt status 1 */
+#define SSTAT2         (shpnt->io_port+0x0d)   /* SCSI interrupt status 2 */
+#define SCSITEST       (shpnt->io_port+0x0e)   /* SCSI test control */
+#define SSTAT3         SCSITEST                /* SCSI interrupt status 3 */
+#define SSTAT4         (shpnt->io_port+0x0f)   /* SCSI status 4 */
+#define SIMODE0                (shpnt->io_port+0x10)   /* SCSI interrupt mode 0 */
+#define SIMODE1                (shpnt->io_port+0x11)   /* SCSI interrupt mode 1 */
+#define DMACNTRL0      (shpnt->io_port+0x12)   /* DMA control 0 */
+#define DMACNTRL1      (shpnt->io_port+0x13)   /* DMA control 1 */
+#define DMASTAT                (shpnt->io_port+0x14)   /* DMA status */
+#define FIFOSTAT       (shpnt->io_port+0x15)   /* FIFO status */
+#define DATAPORT       (shpnt->io_port+0x16)   /* DATA port */
+#define BRSTCNTRL      (shpnt->io_port+0x18)   /* burst control */
+#define PORTA          (shpnt->io_port+0x1a)   /* PORT A */
+#define PORTB          (shpnt->io_port+0x1b)   /* PORT B */
+#define REV            (shpnt->io_port+0x1c)   /* revision */
+#define STACK          (shpnt->io_port+0x1d)   /* stack */
+#define TEST           (shpnt->io_port+0x1e)   /* test register */
+
+/* used in aha152x_porttest */
+#define O_PORTA                (0x1a)                  /* PORT A */
+#define O_PORTB                (0x1b)                  /* PORT B */
+#define O_DMACNTRL1    (0x13)                  /* DMA control 1 */
+#define O_STACK         (0x1d)                  /* stack */
+#define IO_RANGE       0x20
 
 /* bits and bitmasks to ports */
 
index 65b1112140a472c75f8a783140b3551cad5bdae0..07f071b21d53d232293da9fb8f6498d4b4337407 100644 (file)
@@ -593,7 +593,7 @@ void print_hostbyte(int scsiresult)
 }
 #else
 void print_hostbyte(int scsiresult)
-{   printk("Hostbyte=0x%02x ",hostbyte(scsiresult));
+{   printk("Hostbyte=0x%02x ",host_byte(scsiresult));
 }
 #endif
 
index b780a7497bd39c3d4a7ab7535c070242a3150a13..d276c5b16833df527de80e139ef46cbbc51d90a8 100644 (file)
@@ -177,3 +177,10 @@ const char * generic_NCR5380_info (void) {
 }
 
 #include "NCR5380.c"
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = GENERIC_NCR5380;
+
+#include <linux/module.h>
+#include "scsi_module.c"
+#endif
index d7a7ee638beb65bbaa4db9094f598449212e6790..435be2a8f8cc552b8c07120b59f95f638856202b 100644 (file)
@@ -51,8 +51,7 @@ int generic_NCR5380_reset(Scsi_Cmnd *);
 #define CAN_QUEUE 16
 #endif
 
-#ifdef HOSTS_C
-
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define GENERIC_NCR5380 {NULL, NULL, NULL, NULL, \
        "Trantor T128/T128F/T228",              \
@@ -62,7 +61,10 @@ int generic_NCR5380_reset(Scsi_Cmnd *);
        NULL, /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,            \
        /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+
+#ifndef HOSTS_C
+
 #define NCR5380_implementation_fields \
     int port
 
index c004b61b5a110ce6868c6a73f2adca5d6938b39b..e45cb010d41cdd2c0a3b7254ac180c69490fa91f 100644 (file)
@@ -539,3 +539,11 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
 }
 
 #include "NCR5380.c"
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = MV_PAS16;
+
+#include <linux/module.h>
+#include "scsi_module.c"
+#endif
index b62db4e4c7e1215340676625491513629832b2b7..9733792b249cdf6ac1ee6f7b0a7a09a28b4b8080 100644 (file)
@@ -138,7 +138,7 @@ int pas16_reset(Scsi_Cmnd *);
  * macros when this is being used solely for the host stub.
  */
 
-#ifdef HOSTS_C
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define MV_PAS16 {NULL, NULL, NULL, NULL, \
        "Pro Audio Spectrum-16 SCSI",           \
@@ -148,7 +148,8 @@ int pas16_reset(Scsi_Cmnd *);
        /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,                  \
        /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+#ifndef HOSTS_C
 
 #define NCR5380_implementation_fields \
     volatile unsigned short io_port
index b75be8332c24b82494d80ec776fa6301a6c5b016..2c50d3412bf315c3d5ecdf5336e03f72bd589ad7 100644 (file)
@@ -11,7 +11,7 @@
   Copyright 1992, 1993, 1994, 1995 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  Last modified: Sat Nov  4 22:23:54 1995 by root@kai.makisara.fi
+  Last modified: Thu Dec 14 21:51:16 1995 by root@kai.makisara.fi
   Some small formal changes - aeb, 950809
 */
 
    is defined and non-zero. */
 #define DEBUG 0
 
+/* The message level for the debug messages is currently set to KERN_NOTICE
+   so that people can easily see the messages. Later when the debugging messages
+   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
+#define ST_DEB_MSG  KERN_NOTICE
+
 #define MAJOR_NR SCSI_TAPE_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
@@ -114,7 +119,8 @@ st_chk_result(Scsi_Cmnd * SCpnt)
     return 0;
 #if DEBUG
   if (debugging) {
-    printk("st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result,
+    printk(ST_DEB_MSG "st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+          dev, result,
           SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
           SCpnt->data_cmnd[3], SCpnt->data_cmnd[4], SCpnt->data_cmnd[5],
           SCpnt->request_bufflen);
@@ -129,16 +135,18 @@ st_chk_result(Scsi_Cmnd * SCpnt)
       ((sense[0] & 0x70) == 0x70 &&
        scode != NO_SENSE &&
        scode != RECOVERED_ERROR &&
-       scode != UNIT_ATTENTION &&
+/*       scode != UNIT_ATTENTION && */
        scode != BLANK_CHECK &&
        scode != VOLUME_OVERFLOW &&
-       SCpnt->data_cmnd[0] != MODE_SENSE)) {  /* Abnormal conditions for tape */
-    printk("st%d: Error %x. ", dev, result);
+       SCpnt->data_cmnd[0] != MODE_SENSE &&
+       SCpnt->data_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 #if !DEBUG
-    if (driver_byte(result) & DRIVER_SENSE)
+    if (driver_byte(result) & DRIVER_SENSE) {
+      printk(KERN_WARNING "st%d: Error with sense data: ", dev);
       print_sense("st", SCpnt);
+    }
     else
-      printk("\n");
+      printk(KERN_WARNING "st%d: Error %x.\n", dev, result);
 #endif
   }
 
@@ -159,7 +167,7 @@ st_chk_result(Scsi_Cmnd * SCpnt)
        stp = "write";
       else
        stp = "ioctl";
-      printk("st%d: Recovered %s error (%d).\n", dev, stp,
+      printk(ST_DEB_MSG "st%d: Recovered %s error (%d).\n", dev, stp,
             scsi_tapes[dev].recover_count);
     }
 #endif
@@ -212,7 +220,7 @@ st_sleep_done (Scsi_Cmnd * SCpnt)
   }
 #if DEBUG
   else if (debugging)
-    printk("st?: Illegal interrupt device %x\n", st_nbr);
+    printk(KERN_ERR "st?: Illegal interrupt device %x\n", st_nbr);
 #endif
 }
 
@@ -224,7 +232,7 @@ st_do_scsi(Scsi_Cmnd *SCpnt, Scsi_Tape *STp, unsigned char *cmd, int bytes,
 {
   if (SCpnt == NULL)
     if ((SCpnt = allocate_device(NULL, STp->device, 1)) == NULL) {
-      printk("st%d: Can't get SCSI request.\n", TAPE_NR(STp->devt));
+      printk(KERN_ERR "st%d: Can't get SCSI request.\n", TAPE_NR(STp->devt));
       return NULL;
     }
 
@@ -298,7 +306,7 @@ back_over_eof(Scsi_Tape *STp)
 
   SCpnt->request.rq_status = RQ_INACTIVE;
   if ((STp->buffer)->last_result != 0) {
-    printk("st%d: Backing over filemark failed.\n", TAPE_NR(STp->devt));
+    printk(KERN_ERR "st%d: Backing over filemark failed.\n", TAPE_NR(STp->devt));
     if ((STp->mt_status)->mt_fileno >= 0)
       (STp->mt_status)->mt_fileno += 1;
     (STp->mt_status)->mt_blkno = 0;
@@ -322,8 +330,8 @@ flush_write_buffer(Scsi_Tape *STp)
     if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
       if (debugging)
-       printk("st%d: Async write error (flush) %x.\n", TAPE_NR(STp->devt),
-              (STp->buffer)->last_result);
+       printk(ST_DEB_MSG "st%d: Async write error (flush) %x.\n",
+              TAPE_NR(STp->devt), (STp->buffer)->last_result);
 #endif
       if ((STp->buffer)->last_result == INT_MAX)
        return (-ENOSPC);
@@ -342,7 +350,7 @@ flush_write_buffer(Scsi_Tape *STp)
                STp->block_size) * STp->block_size;
 #if DEBUG
     if (debugging)
-      printk("st%d: Flushing %d bytes.\n", TAPE_NR(STp->devt), transfer);
+      printk(ST_DEB_MSG "st%d: Flushing %d bytes.\n", TAPE_NR(STp->devt), transfer);
 #endif
     memset((STp->buffer)->b_data + offset, 0, transfer - offset);
 
@@ -359,7 +367,7 @@ flush_write_buffer(Scsi_Tape *STp)
       return (-EBUSY);
 
     if ((STp->buffer)->last_result_fatal != 0) {
-      printk("st%d: Error on flush.\n", TAPE_NR(STp->devt));
+      printk(KERN_ERR "st%d: Error on flush.\n", TAPE_NR(STp->devt));
       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
          (SCpnt->sense_buffer[2] & 0x40) &&
          (SCpnt->sense_buffer[2] & 0x0f) != VOLUME_OVERFLOW) {
@@ -450,9 +458,12 @@ scsi_tape_open(struct inode * inode, struct file * filp)
       return (-ENXIO);
     STp = &(scsi_tapes[dev]);
     if (STp->in_use) {
-      printk("st%d: Device already in use.\n", dev);
+#if DEBUG
+      printk(ST_DEB_MSG "st%d: Device already in use.\n", dev);
+#endif
       return (-EBUSY);
     }
+    STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
 
     /* Allocate buffer for this user */
     for (i=0; i < st_nbr_buffers; i++)
@@ -461,7 +472,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     if (i >= st_nbr_buffers) {
       STp->buffer = new_tape_buffer(FALSE);
       if (STp->buffer == NULL) {
-       printk("st%d: No free buffers.\n", dev);
+       printk(KERN_WARNING "st%d: No free buffers.\n", dev);
        return (-EBUSY);
       }
     }
@@ -509,7 +520,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
          (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) {
        (STp->mt_status)->mt_fileno = STp->drv_block = 0 ;
-       printk("st%d: No tape.\n", dev);
+       printk(KERN_NOTICE "st%d: No tape.\n", dev);
        STp->ready = ST_NO_TAPE;
       } else {
        (STp->mt_status)->mt_fileno = STp->drv_block = (-1);
@@ -540,7 +551,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
        (STp->buffer)->b_data[5];
 #if DEBUG
       if (debugging)
-       printk("st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
+       printk(ST_DEB_MSG "st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
               STp->max_block);
 #endif
     }
@@ -548,7 +559,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
       STp->min_block = STp->max_block = (-1);
 #if DEBUG
       if (debugging)
-       printk("st%d: Can't read block limits.\n", dev);
+       printk(ST_DEB_MSG "st%d: Can't read block limits.\n", dev);
 #endif
     }
 
@@ -561,7 +572,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     if ((STp->buffer)->last_result_fatal != 0) {
 #if DEBUG
       if (debugging)
-       printk("st%d: No Mode Sense.\n", dev);
+       printk(ST_DEB_MSG "st%d: No Mode Sense.\n", dev);
 #endif
       STp->block_size = ST_DEFAULT_BLOCK;  /* Educated guess (?) */
       (STp->buffer)->last_result_fatal = 0;  /* Prevent error propagation */
@@ -571,7 +582,8 @@ scsi_tape_open(struct inode * inode, struct file * filp)
 
 #if DEBUG
       if (debugging)
-       printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
+       printk(ST_DEB_MSG "st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
+              dev,
               (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
               (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
 #endif
@@ -583,7 +595,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
          (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
 #if DEBUG
        if (debugging)
-         printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
+         printk(ST_DEB_MSG "st%d: Density %x, tape length: %x, drv buffer: %d\n",
                 dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
                 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
                 STp->drv_buffer);
@@ -592,7 +604,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
 
       if (STp->block_size > (STp->buffer)->buffer_size &&
          !enlarge_buffer(STp->buffer, STp->block_size)) {
-       printk("st%d: Blocksize %d too large for buffer.\n", dev,
+       printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n", dev,
               STp->block_size);
        (STp->buffer)->in_use = 0;
        STp->in_use = 0;
@@ -610,7 +622,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
 
 #if DEBUG
     if (debugging)
-      printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
+      printk(ST_DEB_MSG "st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
             STp->block_size, (STp->buffer)->buffer_size,
             (STp->buffer)->buffer_blocks);
 #endif
@@ -619,7 +631,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
       STp->write_prot = 1;
 #if DEBUG
       if (debugging)
-       printk( "st%d: Write protected\n", dev);
+       printk(ST_DEB_MSG "st%d: Write protected\n", dev);
 #endif
       if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
        (STp->buffer)->in_use = 0;
@@ -642,7 +654,6 @@ scsi_tape_open(struct inode * inode, struct file * filp)
 scsi_tape_close(struct inode * inode, struct file * filp)
 {
     int result;
-    int rewind;
     static unsigned char cmd[10];
     Scsi_Cmnd * SCpnt;
     Scsi_Tape * STp;
@@ -650,8 +661,6 @@ scsi_tape_close(struct inode * inode, struct file * filp)
     int dev;
 
     dev = TAPE_NR(devt);
-    rewind = (MINOR(devt) & 0x80) == 0;
-
     STp = &(scsi_tapes[dev]);
 
     if ( STp->rw == ST_WRITING && !(STp->device)->was_reset) {
@@ -660,9 +669,10 @@ scsi_tape_close(struct inode * inode, struct file * filp)
 
 #if DEBUG
       if (debugging) {
-       printk("st%d: File length %ld bytes.\n", dev, (long)(filp->f_pos));
-       printk("st%d: Async write waits %d, finished %d.\n", dev,
-              STp->nbr_waits, STp->nbr_finished);
+       printk(ST_DEB_MSG "st%d: File length %ld bytes.\n",
+              dev, (long)(filp->f_pos));
+       printk(ST_DEB_MSG "st%d: Async write waits %d, finished %d.\n",
+              dev, STp->nbr_waits, STp->nbr_finished);
       }
 #endif
 
@@ -679,7 +689,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
        SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
 
        if ((STp->buffer)->last_result_fatal != 0)
-         printk("st%d: Error on write filemark.\n", dev);
+         printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
        else {
          if ((STp->mt_status)->mt_fileno >= 0)
              (STp->mt_status)->mt_fileno++ ;
@@ -691,10 +701,11 @@ scsi_tape_close(struct inode * inode, struct file * filp)
 
 #if DEBUG
       if (debugging)
-       printk("st%d: Buffer flushed, %d EOF(s) written\n", dev, cmd[4]);
+       printk(ST_DEB_MSG "st%d: Buffer flushed, %d EOF(s) written\n",
+              dev, cmd[4]);
 #endif
     }
-    else if (!rewind) {
+    else if (!STp->rew_at_close) {
 #if ST_IN_FILE_POS
       flush_buffer(inode, filp, 0);
 #else
@@ -703,7 +714,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
 #endif
     }
 
-    if (rewind)
+    if (STp->rew_at_close)
       st_int_ioctl(inode, filp, MTREW, 1);
 
     if (STp->door_locked == ST_LOCKED_AUTO)
@@ -749,7 +760,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
 
 #if DEBUG
     if (!STp->in_use) {
-      printk("st%d: Incorrect device.\n", dev);
+      printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
@@ -758,18 +769,18 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
       return (-EACCES);
 
     if (STp->block_size == 0 &&
-       count > (STp->buffer)->buffer_size &&
-       !enlarge_buffer(STp->buffer, count))
+       count > (STp->buffer)->buffer_size &&
+       !enlarge_buffer(STp->buffer, count))
       return (-EOVERFLOW);
 
     if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
-       !st_int_ioctl(inode, filp, MTLOCK, 0))
+       !st_int_ioctl(inode, filp, MTLOCK, 0))
       STp->door_locked = ST_LOCKED_AUTO;
 
     if (STp->rw == ST_READING) {
       retval = flush_buffer(inode, filp, 0);
       if (retval)
-       return retval;
+       return retval;
       STp->rw = ST_WRITING;
     }
 
@@ -781,7 +792,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
       if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
        if (debugging)
-         printk("st%d: Async write error (write) %x.\n", dev,
+         printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n", dev,
                 (STp->buffer)->last_result);
 #endif
        if ((STp->buffer)->last_result == INT_MAX) {
@@ -793,7 +804,6 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
        return retval;
       }
     }
-
     if (STp->eof == ST_EOM_OK)
       return (-ENOSPC);
     else if (STp->eof == ST_EOM_ERROR)
@@ -852,7 +862,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
       if ((STp->buffer)->last_result_fatal != 0) {
 #if DEBUG
        if (debugging)
-         printk("st%d: Error on write:\n", dev);
+         printk(ST_DEB_MSG "st%d: Error on write:\n", dev);
 #endif
        if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
            (SCpnt->sense_buffer[2] & 0x40)) {
@@ -880,7 +890,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
            retval = (-ENOSPC); /* EOM within current request */
 #if DEBUG
            if (debugging)
-             printk("st%d: EOM with %d bytes unwritten.\n",
+             printk(ST_DEB_MSG "st%d: EOM with %d bytes unwritten.\n",
                     dev, transfer);
 #endif
          }
@@ -890,7 +900,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
            retval = (-EIO); /* EOM for old data */
 #if DEBUG
            if (debugging)
-             printk("st%d: EOM with lost data.\n", dev);
+             printk(ST_DEB_MSG "st%d: EOM with lost data.\n", dev);
 #endif
          }
        }
@@ -994,7 +1004,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
       return (-EIO);
 #if DEBUG
     if (!STp->in_use) {
-      printk("st%d: Incorrect device.\n", dev);
+      printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
@@ -1023,7 +1033,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
 
 #if DEBUG
     if (debugging && STp->eof != ST_NOEOF)
-      printk("st%d: EOF flag up. Bytes %d\n", dev,
+      printk(ST_DEB_MSG "st%d: EOF flag up. Bytes %d\n", dev,
             (STp->buffer)->buffer_bytes);
 #endif
     if (((STp->buffer)->buffer_bytes == 0) &&
@@ -1070,7 +1080,8 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
        if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
          if (debugging)
-           printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
+           printk(ST_DEB_MSG "st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+                  dev,
                   SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
                   SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
                   SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
@@ -1097,7 +1108,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                  (STp->buffer)->buffer_bytes = bytes - transfer;
                }
                else {
-                 printk("st%d: Incorrect block size.\n", dev);
+                 printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
                  SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
                  return (-EIO);
                }
@@ -1111,7 +1122,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                    bytes - transfer * STp->block_size;
 #if DEBUG
                if (debugging)
-                 printk("st%d: EOM detected (%d bytes read).\n", dev,
+                 printk(ST_DEB_MSG "st%d: EOM detected (%d bytes read).\n", dev,
                         (STp->buffer)->buffer_bytes);
 #endif
              }
@@ -1124,7 +1135,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                    bytes - transfer * STp->block_size;
 #if DEBUG
                if (debugging)
-                 printk(
+                 printk(ST_DEB_MSG
                    "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
                         dev, (STp->buffer)->buffer_bytes, total);
 #endif
@@ -1133,7 +1144,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
            else { /* nonzero sense key */
 #if DEBUG
              if (debugging)
-               printk("st%d: Tape error while reading.\n", dev);
+               printk(ST_DEB_MSG "st%d: Tape error while reading.\n", dev);
 #endif
              SCpnt->request.rq_status = RQ_INACTIVE;
              STp->drv_block = (-1);
@@ -1143,7 +1154,8 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                       (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
 #if DEBUG
                if (debugging)
-                 printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
+                 printk(ST_DEB_MSG
+                        "st%d: Zero returned for first BLANK CHECK after EOF.\n",
                         dev);
 #endif
                STp->eof = ST_EOD;
@@ -1175,7 +1187,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
       if ((STp->buffer)->buffer_bytes > 0) {
 #if DEBUG
        if (debugging && STp->eof != ST_NOEOF)
-         printk("st%d: EOF up. Left %d, needed %d.\n", dev,
+         printk(ST_DEB_MSG "st%d: EOF up. Left %d, needed %d.\n", dev,
                 (STp->buffer)->buffer_bytes, count - total);
 #endif
        transfer = (STp->buffer)->buffer_bytes < count - total ?
@@ -1236,24 +1248,24 @@ st_set_options(struct inode * inode, long options)
     STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
 #if DEBUG
     debugging = (options & MT_ST_DEBUGGING) != 0;
-    printk(
-"st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
-          dev, STp->do_buffer_writes, STp->do_async_writes,
-          STp->do_read_ahead);
-    printk("              two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
-          STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
+    printk(ST_DEB_MSG
+          "st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
+          dev, STp->do_buffer_writes, STp->do_async_writes, STp->do_read_ahead);
+    printk(ST_DEB_MSG
+          "st%d:          two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
+          dev, STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
 #endif
   }
   else if ((options & MT_ST_OPTIONS) == MT_ST_WRITE_THRESHOLD) {
     value = (options & ~MT_ST_OPTIONS) * ST_BLOCK_SIZE;
     if (value < 1 || value > st_buffer_size) {
-      printk("st: Write threshold %d too small or too large.\n",
+      printk(KERN_WARNING "st: Write threshold %d too small or too large.\n",
             value);
       return (-EIO);
     }
     STp->write_threshold = value;
 #if DEBUG
-    printk("st%d: Write threshold set to %d bytes.\n", dev,
+    printk(ST_DEB_MSG "st%d: Write threshold set to %d bytes.\n", dev,
           STp->write_threshold);
 #endif
   }
@@ -1297,8 +1309,8 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-        printk("st%d: Spacing tape forward over %d filemarks.\n", dev,
-               cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+        printk(ST_DEB_MSG "st%d: Spacing tape forward over %d filemarks.\n",
+               dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (fileno >= 0)
         fileno += arg;
@@ -1318,7 +1330,8 @@ st_int_ioctl(struct inode * inode,struct file * file,
         if (cmd[2] & 0x80)
           ltmp = 0xff000000;
         ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-        printk("st%d: Spacing tape backward over %ld filemarks.\n", dev, (-ltmp));
+        printk(ST_DEB_MSG "st%d: Spacing tape backward over %ld filemarks.\n",
+               dev, (-ltmp));
        }
 #endif
        if (fileno >= 0)
@@ -1334,7 +1347,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-        printk("st%d: Spacing tape forward %d blocks.\n", dev,
+        printk(ST_DEB_MSG "st%d: Spacing tape forward %d blocks.\n", dev,
                cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (blkno >= 0)
@@ -1353,7 +1366,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
         if (cmd[2] & 0x80)
           ltmp = 0xff000000;
         ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-        printk("st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp));
+        printk(ST_DEB_MSG "st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp));
        }
 #endif
        if (blkno >= 0)
@@ -1368,7 +1381,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-        printk("st%d: Spacing tape forward %d setmarks.\n", dev,
+        printk(ST_DEB_MSG "st%d: Spacing tape forward %d setmarks.\n", dev,
                cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (arg != 0) {
@@ -1388,7 +1401,8 @@ st_int_ioctl(struct inode * inode,struct file * file,
         if (cmd[2] & 0x80)
           ltmp = 0xff000000;
         ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-        printk("st%d: Spacing tape backward %ld setmarks.\n", dev, (-ltmp));
+        printk(ST_DEB_MSG "st%d: Spacing tape backward %ld setmarks.\n",
+               dev, (-ltmp));
        }
 #endif
        if (arg != 0) {
@@ -1410,10 +1424,10 @@ st_int_ioctl(struct inode * inode,struct file * file,
 #if DEBUG
        if (debugging) {
         if (cmd_in == MTWEOF)
-          printk("st%d: Writing %d filemarks.\n", dev,
+          printk(ST_DEB_MSG "st%d: Writing %d filemarks.\n", dev,
                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
         else
-          printk("st%d: Writing %d setmarks.\n", dev,
+          printk(ST_DEB_MSG "st%d: Writing %d setmarks.\n", dev,
                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
        }
 #endif
@@ -1430,26 +1444,32 @@ st_int_ioctl(struct inode * inode,struct file * file,
 #endif
 #if DEBUG
        if (debugging)
-        printk("st%d: Rewinding tape.\n", dev);
+        printk(ST_DEB_MSG "st%d: Rewinding tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break; 
      case MTOFFL:
+     case MTLOAD:
+     case MTUNLOAD:
        cmd[0] = START_STOP;
+       if (cmd_in == MTLOAD)
+        cmd[4] |= 1;
 #if ST_NOWAIT
        cmd[1] = 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
+#else
+       timeout = ST_LONG_TIMEOUT * 8;
 #endif
 #if DEBUG
        if (debugging)
-        printk("st%d: Unloading tape.\n", dev);
+        printk(ST_DEB_MSG "st%d: Unloading tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break; 
      case MTNOP:
 #if DEBUG
        if (debugging)
-        printk("st%d: No op on tape.\n", dev);
+        printk(ST_DEB_MSG "st%d: No op on tape.\n", dev);
 #endif
        return 0;  /* Should do something ? */
        break;
@@ -1462,7 +1482,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = 3;
 #if DEBUG
        if (debugging)
-        printk("st%d: Retensioning tape.\n", dev);
+        printk(ST_DEB_MSG "st%d: Retensioning tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0;
        break; 
@@ -1484,7 +1504,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[1] = 3;
 #if DEBUG
        if (debugging)
-        printk("st%d: Spacing to end of recorded medium.\n", dev);
+        printk(ST_DEB_MSG "st%d: Spacing to end of recorded medium.\n", dev);
 #endif
        blkno = 0;
        at_sm = 0;
@@ -1502,7 +1522,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
 #endif
 #if DEBUG
        if (debugging)
-        printk("st%d: Erasing tape.\n", dev);
+        printk(ST_DEB_MSG "st%d: Erasing tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break;
@@ -1511,7 +1531,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = SCSI_REMOVAL_PREVENT;
 #if DEBUG
        if (debugging)
-        printk("st%d: Locking drive door.\n", dev);
+        printk(ST_DEB_MSG "st%d: Locking drive door.\n", dev);
 #endif;
        break;
      case MTUNLOCK:
@@ -1519,21 +1539,9 @@ st_int_ioctl(struct inode * inode,struct file * file,
        cmd[4] = SCSI_REMOVAL_ALLOW;
 #if DEBUG
        if (debugging)
-        printk("st%d: Unlocking drive door.\n", dev);
+        printk(ST_DEB_MSG "st%d: Unlocking drive door.\n", dev);
 #endif;
        break;
-     case MTLOAD:
-     case MTUNLOAD:
-       cmd[0] = START_STOP;
-       if (cmd_in == MTLOAD)
-        cmd[4] |= 1;
-#if ST_NOWAIT
-       cmd[1] |= 2;  /* Don't wait for completion */
-       timeout = ST_TIMEOUT;
-#else
-       timeout = ST_LONG_TIMEOUT * 8;
-#endif
-       break;
      case MTSEEK:
        if ((STp->device)->scsi_level < SCSI_2) {
         cmd[0] = QFA_SEEK_BLOCK;
@@ -1556,7 +1564,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
 #endif
 #if DEBUG
        if (debugging)
-        printk("st%d: Seeking tape to block %ld.\n", dev, arg);
+        printk(ST_DEB_MSG "st%d: Seeking tape to block %ld.\n", dev, arg);
 #endif
        fileno = blkno = (-1);
        at_sm = 0;
@@ -1570,7 +1578,7 @@ st_int_ioctl(struct inode * inode,struct file * file,
           arg != 0 &&
           (arg < STp->min_block || arg > STp->max_block ||
            arg > st_buffer_size)) {
-        printk("st%d: Illegal block size.\n", dev);
+        printk(KERN_WARNING "st%d: Illegal block size.\n", dev);
         return (-EINVAL);
        }
        cmd[0] = MODE_SELECT;
@@ -1598,21 +1606,20 @@ st_int_ioctl(struct inode * inode,struct file * file,
 #if DEBUG
        if (debugging) {
         if (cmd_in == MTSETBLK)
-          printk("st%d: Setting block size to %d bytes.\n", dev,
+          printk(ST_DEB_MSG "st%d: Setting block size to %d bytes.\n", dev,
                  (STp->buffer)->b_data[9] * 65536 +
                  (STp->buffer)->b_data[10] * 256 +
                  (STp->buffer)->b_data[11]);
         else if (cmd_in == MTSETDENSITY)
-          printk("st%d: Setting density code to %x.\n", dev,
+          printk(ST_DEB_MSG "st%d: Setting density code to %x.\n", dev,
                  (STp->buffer)->b_data[4]);
         else
-          printk("st%d: Setting drive buffer code to %d.\n", dev,
+          printk(ST_DEB_MSG "st%d: Setting drive buffer code to %d.\n", dev,
                  ((STp->buffer)->b_data[2] >> 4) & 7);
        }
 #endif
        break;
      default:
-       printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
        return (-ENOSYS);
      }
 
@@ -1665,6 +1672,11 @@ st_int_ioctl(struct inode * inode,struct file * file,
        STp->eof = ST_NOEOF;
        STp->eof_hit = 0;
      }
+     if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
+       STp->rew_at_close = 0;
+     else if (cmd_in == MTLOAD)
+       STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+
    } else {  /* SCSI command was not completely successful */
      if (SCpnt->sense_buffer[2] & 0x40) {
        if (cmd_in != MTBSF && cmd_in != MTBSFM &&
@@ -1745,7 +1757,7 @@ st_ioctl(struct inode * inode,struct file * file,
    STp = &(scsi_tapes[dev]);
 #if DEBUG
    if (debugging && !STp->in_use) {
-     printk("st%d: Incorrect device.\n", dev);
+     printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
      return (-EIO);
    }
 #endif
@@ -1772,6 +1784,18 @@ st_ioctl(struct inode * inode,struct file * file,
      memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
 
      if (!(STp->device)->was_reset) {
+
+       if (STp->eof_hit) {
+        if (mtc.mt_op == MTFSF || mtc.mt_op == MTEOM) {
+          mtc.mt_count -= 1;
+          (STp->mt_status)->mt_fileno += 1;
+        }
+        else if (mtc.mt_op == MTBSF) {
+          mtc.mt_count += 1;
+          (STp->mt_status)->mt_fileno += 1;
+        }
+       }
+
        i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
                        mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
                        mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
@@ -1796,7 +1820,8 @@ st_ioctl(struct inode * inode,struct file * file,
        if (STp->door_locked != ST_UNLOCKED &&
           STp->door_locked != ST_LOCK_FAILS) {
         if (st_int_ioctl(inode, file, MTLOCK, 0)) {
-          printk("st%d: Could not relock door after bus reset.\n", dev);
+          printk(KERN_NOTICE "st%d: Could not relock door after bus reset.\n",
+                 dev);
           STp->door_locked = ST_UNLOCKED;
         }
        }
@@ -1874,7 +1899,7 @@ st_ioctl(struct inode * inode,struct file * file,
        return (-EIO);
 #if DEBUG
      if (debugging)
-       printk("st%d: get tape position.\n", dev);
+       printk(ST_DEB_MSG "st%d: get tape position.\n", dev);
 #endif
      if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
        return (-EINVAL);
@@ -1904,7 +1929,7 @@ st_ioctl(struct inode * inode,struct file * file,
        mt_pos.mt_blkno = (-1);
 #if DEBUG
        if (debugging)
-        printk("st%d: Can't read tape position.\n", dev);
+        printk(ST_DEB_MSG "st%d: Can't read tape position.\n", dev);
 #endif
        result = (-EIO);
      }
@@ -1960,14 +1985,15 @@ new_tape_buffer( int from_initialization )
     }
   }
   if (!tb) {
-    printk("st: Can't allocate new tape buffer (nbr %d).\n", st_nbr_buffers);
+    printk(KERN_NOTICE "st: Can't allocate new tape buffer (nbr %d).\n",
+          st_nbr_buffers);
     return NULL;
   }
 
 #if DEBUG
   if (debugging)
-    printk("st: Allocated tape buffer %d (%d bytes).\n", st_nbr_buffers,
-          a_size);
+    printk(ST_DEB_MSG "st: Allocated tape buffer %d (%d bytes).\n",
+          st_nbr_buffers, a_size);
 #endif
   tb->in_use = 0;
   tb->buffer_size = a_size;
@@ -1996,7 +2022,7 @@ enlarge_buffer(ST_buffer *STbuffer, int new_size)
 
 #if DEBUG
   if (debugging)
-    printk("st: Buffer enlarged to %d bytes.\n", a_size);
+    printk(ST_DEB_MSG "st: Buffer enlarged to %d bytes.\n", a_size);
 #endif
 
   STbuffer->orig_b_data = STbuffer->b_data;
@@ -2021,14 +2047,15 @@ normalize_buffer(ST_buffer *STbuffer)
 
 #if DEBUG
   if (debugging)
-    printk("st: Buffer normalized to %d bytes.\n", STbuffer->buffer_size);
+    printk(ST_DEB_MSG "st: Buffer normalized to %d bytes.\n",
+          STbuffer->buffer_size);
 #endif
 }
 
 
 /* Set the boot options. Syntax: st=xxx,yyy
-   where xxx is buffer size in 512 byte blocks and yyy is write threshold
-   in 512 byte blocks. */
+   where xxx is buffer size in 1024 byte blocks and yyy is write threshold
+   in 1024 byte blocks. */
        void
 st_setup(char *str, int *ints)
 {
@@ -2107,7 +2134,7 @@ static int st_detect(Scsi_Device * SDp)
 {
   if(SDp->type != TYPE_TAPE) return 0;
 
-  printk("Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
+  printk(KERN_NOTICE "Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
         st_template.dev_noticed++,
         SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); 
   
@@ -2129,7 +2156,7 @@ static int st_init()
 
   if(!st_registered) {
     if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
-      printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
+      printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR);
       return 1;
     }
     st_registered++;
@@ -2143,13 +2170,13 @@ static int st_init()
     (Scsi_Tape *) scsi_init_malloc(st_template.dev_max * sizeof(Scsi_Tape),
                                   GFP_ATOMIC);
   if (scsi_tapes == NULL) {
-    printk("Unable to allocate descriptors for SCSI tapes.\n");
+    printk(KERN_ERR "Unable to allocate descriptors for SCSI tapes.\n");
     unregister_chrdev(SCSI_TAPE_MAJOR, "st");
     return 1;
   }
 
 #if DEBUG
-  printk("st: Buffer size %d bytes, write threshold %d bytes.\n",
+  printk(ST_DEB_MSG "st: Buffer size %d bytes, write threshold %d bytes.\n",
         st_buffer_size, st_write_threshold);
 #endif
 
@@ -2185,7 +2212,7 @@ static int st_init()
     (ST_buffer **) scsi_init_malloc(st_template.dev_max * sizeof(ST_buffer *),
                                    GFP_ATOMIC);
   if (st_buffers == NULL) {
-    printk("Unable to allocate tape buffer pointers.\n");
+    printk(KERN_ERR "Unable to allocate tape buffer pointers.\n");
     unregister_chrdev(SCSI_TAPE_MAJOR, "st");
     scsi_init_free((char *) scsi_tapes,
                   st_template.dev_max * sizeof(Scsi_Tape));
@@ -2204,7 +2231,7 @@ static int st_init()
   for (i=st_nbr_buffers=0; i < target_nbr; i++) {
     if (!new_tape_buffer(TRUE)) {
       if (i == 0) {
-       printk("Can't continue without at least one tape buffer.\n");
+       printk(KERN_ERR "Can't continue without at least one tape buffer.\n");
        unregister_chrdev(SCSI_TAPE_MAJOR, "st");
        scsi_init_free((char *) st_buffers,
                       st_template.dev_max * sizeof(ST_buffer *));
@@ -2212,7 +2239,7 @@ static int st_init()
                       st_template.dev_max * sizeof(Scsi_Tape));
        return 1;
       }
-      printk("Number of tape buffers adjusted.\n");
+      printk(KERN_INFO "Number of tape buffers adjusted.\n");
       break;
     }
   }
index 476e543b94e514894b6e8797e07b078e1ac7d9bd..391d0e2ec255bf9507212ee7c30618ca89e6cd0d 100644 (file)
@@ -45,6 +45,7 @@ typedef struct {
   unsigned char fast_mteom;
   unsigned char density;
   unsigned char door_locked;
+  unsigned char rew_at_close;
   ST_buffer * buffer;
   struct semaphore sem;
   int block_size;
index 44a1d6b3d10c6814dc023fee8139ca6ea12279dd..7adc48d3ea62e6a3d54dadbe267390940ee3820e 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright 1995 Kai Makisara.
 
-   Last modified: Sun Sep 24 11:46:15 1995 by root@kai.makisara.fi
+   Last modified: Thu Dec 14 21:51:27 1995 by root@kai.makisara.fi
 */
 
 #ifndef _ST_OPTIONS_H
index 0e89d1edba6718a00fa1dec88267b62802655b1e..ddcb72b7246fba9353c413ecf13f9c8e87c2d6e8 100644 (file)
@@ -393,3 +393,10 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
 }
 
 #include "NCR5380.c"
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = TRANTOR_T128;
+
+#include "scsi_module.c"
+#endif
index dfb20ccfc2df4e29bad50abef5525dc89ea816dd..009161374ba97c5c033271ef266f59ccc470d5c9 100644 (file)
@@ -115,7 +115,7 @@ int t128_reset(Scsi_Cmnd *);
  * macros when this is being used solely for the host stub.
  */
 
-#ifdef HOSTS_C
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define TRANTOR_T128 {NULL, NULL, NULL, NULL, \
        "Trantor T128/T128F/T228", t128_detect, NULL,  \
@@ -125,7 +125,9 @@ int t128_reset(Scsi_Cmnd *);
        /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,                  \
        /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+
+#ifndef(HOSTS_C)
 
 #define NCR5380_implementation_fields \
     volatile unsigned char *base
index f88a87764bda9ce44c8242ecaf90a9a5bfff5256..8406dabbd979ef11aaa05e143403ba69bfe8b4c7 100644 (file)
@@ -588,7 +588,7 @@ repeat0:
                                 continue;
                         }
                         
-                        if (bh->b_count || bh->b_size != size)
+                        if (bh->b_count || buffer_protected(bh) || bh->b_size != size)
                                  continue;
                         
                         /* Buffers are written in the order they are placed 
@@ -632,6 +632,8 @@ repeat0:
                         panic("Busy buffer in candidate list\n");
                if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1)
                         panic("Shared buffer in candidate list\n");
+               if (buffer_protected(bh))
+                       panic("Protected buffer in candidate list\n");
                if (BADNESS(bh)) panic("Buffer in candidate list with BADNESS != 0\n");
                
                if(bh->b_dev == B_FREE)
@@ -780,7 +782,7 @@ void refile_buffer(struct buffer_head * buf)
        }
        if (buffer_dirty(buf))
                dispose = BUF_DIRTY;
-       else if (mem_map[MAP_NR((unsigned long) buf->b_data)].count > 1)
+       else if ((mem_map[MAP_NR((unsigned long) buf->b_data)].count > 1) || buffer_protected(buf))
                dispose = BUF_SHARED;
        else if (buffer_locked(buf))
                dispose = BUF_LOCKED;
@@ -838,6 +840,10 @@ void __bforget(struct buffer_head * buf)
                printk("Aieee... bforget(): shared buffer\n");
                return;
        }
+       if (buffer_protected(buf)) {
+               printk("Aieee... bforget(): protected buffer\n");
+               return;
+       }
        mark_buffer_clean(buf);
        buf->b_count = 0;
        remove_from_queues(buf);
@@ -1315,7 +1321,8 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp,
        do {
                if (!tmp)
                        return 0;
-               if (tmp->b_count || buffer_dirty(tmp) || buffer_locked(tmp) || tmp->b_wait)
+               if (tmp->b_count || buffer_protected(tmp) ||
+                   buffer_dirty(tmp) || buffer_locked(tmp) || tmp->b_wait)
                        return 0;
                if (priority && buffer_touched(tmp))
                        return 0;
@@ -1465,7 +1472,8 @@ static int shrink_specific_buffers(unsigned int priority, int size)
                bh = free_list[isize];
                if(!bh) continue;
                for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
-                       if (bh->b_count || !bh->b_this_page)
+                       if (bh->b_count || buffer_protected(bh) ||
+                           !bh->b_this_page)
                                 continue;
                        if (!age_of((unsigned long) bh->b_data) &&
                            try_to_free(bh, &bh, 6))
@@ -1494,7 +1502,8 @@ static int shrink_specific_buffers(unsigned int priority, int size)
                        /* We may have stalled while waiting for I/O
                           to complete. */
                        if(bh->b_list != nlist) goto repeat1;
-                       if (bh->b_count || !bh->b_this_page)
+                       if (bh->b_count || buffer_protected(bh) ||
+                           !bh->b_this_page)
                                 continue;
                        if(size && bh->b_size != size) continue;
                        if (buffer_locked(bh))
@@ -1530,6 +1539,7 @@ void show_buffers(void)
 {
        struct buffer_head * bh;
        int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
+       int protected = 0;
        int shared;
        int nlist, isize;
 
@@ -1538,13 +1548,15 @@ void show_buffers(void)
        printk("Buffer blocks:   %6d\n",nr_buffers);
 
        for(nlist = 0; nlist < NR_LIST; nlist++) {
-         shared = found = locked = dirty = used = lastused = 0;
+         shared = found = locked = dirty = used = lastused = protected = 0;
          bh = lru_list[nlist];
          if(!bh) continue;
          do {
                found++;
                if (buffer_locked(bh))
                        locked++;
+               if (buffer_protected(bh))
+                       protected++;
                if (buffer_dirty(bh))
                        dirty++;
                if(mem_map[MAP_NR(((unsigned long) bh->b_data))].count !=1) shared++;
@@ -1552,10 +1564,11 @@ void show_buffers(void)
                        used++, lastused = found;
                bh = bh->b_next_free;
              } while (bh != lru_list[nlist]);
-       printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n",
-               nlist, found, used, lastused, locked, dirty, shared);
+       printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, "
+              "%d protected, %d dirty %d shrd\n",
+               nlist, found, used, lastused, locked, protected, dirty, shared);
        };
-       printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared\n");
+       printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared \n");
        for(isize = 0; isize<NR_SIZES; isize++){
                printk("%5d [%5d]: %7d ", bufferindex_size[isize],
                       buffers_lav[isize], nr_free[isize]);
@@ -1587,7 +1600,8 @@ static inline int try_to_reassign(struct buffer_head * bh, struct buffer_head **
                if (!tmp)
                         return 0;
                
-               if (tmp->b_count || buffer_dirty(tmp) || buffer_locked(tmp))
+               if (tmp->b_count || buffer_protected(tmp) ||
+                   buffer_dirty(tmp) || buffer_locked(tmp))
                         return 0;
                tmp = tmp->b_this_page;
        } while (tmp != bh);
@@ -1792,8 +1806,11 @@ static int bdflush_running = 0;
 
 static void wakeup_bdflush(int wait)
 {
-       if(!bdflush_running){
-               printk("Warning - bdflush not running\n");
+       extern int      rd_loading;
+       
+       if (!bdflush_running){
+               if (!rd_loading)
+                       printk("Warning - bdflush not running\n");
                sync_buffers(0,0);
                return;
        };
index 9001901d1d30ee9196dd6f27c1247c867159fdc7..5ef0e655becee65e0a3413e82f816c4716f87731 100644 (file)
@@ -232,7 +232,7 @@ struct quad_buffer_head {
 /* forwards */
 
 static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
-                     int *lowercase, int *conv);
+                     int *lowercase, int *conv, int *nocheck);
 static int check_warn(int not_ok,
                      const char *p1, const char *p2, const char *p3);
 static int zerop(void *addr, unsigned len);
@@ -344,6 +344,7 @@ struct super_block *hpfs_read_super(struct super_block *s,
        int lowercase;
        int conv;
        int dubious;
+       int nocheck;
 
        MOD_INC_USE_COUNT;
 
@@ -351,7 +352,8 @@ struct super_block *hpfs_read_super(struct super_block *s,
         * Get the mount options
         */
 
-       if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv)) {
+       if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv,
+                                &nocheck)) {
                printk("HPFS: syntax error in mount options.  Not mounted.\n");
                s->s_dev = 0;
                MOD_DEC_USE_COUNT;
@@ -414,7 +416,7 @@ struct super_block *hpfs_read_super(struct super_block *s,
         * so don't
         */
 
-       if (dubious)
+       if (dubious && !nocheck)
                goto bail2;
 
        dubious |= check_warn((spareblock->n_dnode_spares !=
@@ -544,7 +546,7 @@ static int zerop(void *addr, unsigned len)
  */
 
 static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
-                     int *lowercase, int *conv)
+                     int *lowercase, int *conv, int *nocheck)
 {
        char *p, *rhs;
 
@@ -553,6 +555,7 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
        *umask = current->fs->umask;
        *lowercase = 1;
        *conv = CONV_BINARY;
+        *nocheck = 0;
 
        if (!opts)
                return 1;
@@ -599,6 +602,8 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
                        else
                                return 0;
                }
+               else if (!strcmp(p,"nocheck")) 
+                       *nocheck=1;
                else
                        return 1;
        }
index 9fbfd4725807f991193b6848fc41aa8fa9b9352a..75971cb4b94f722abb5e99652de2d85f91efddfc 100644 (file)
@@ -150,7 +150,7 @@ void clear_inode(struct inode * inode)
 
        wait_on_inode(inode);
        if (IS_WRITABLE(inode)) {
-               if (inode->i_sb->dq_op)
+               if (inode->i_sb && inode->i_sb->dq_op)
                        inode->i_sb->dq_op->drop(inode);
        }
        remove_inode_hash(inode);
@@ -415,7 +415,7 @@ repeat:
 
        inode->i_count--;
        if (IS_WRITABLE(inode)) {
-               if (inode->i_sb->dq_op)
+               if (inode->i_sb && inode->i_sb->dq_op)
                        inode->i_sb->dq_op->drop(inode);
        }
 
@@ -540,6 +540,7 @@ repeat:
        inode->i_sb = sb;
        inode->i_dev = sb->s_dev;
        inode->i_ino = nr;
+       inode->i_flags = sb->s_flags;
        put_last_free(inode);
        insert_inode_hash(inode);
        read_inode(inode);
index 89d5b4a2d29d68c56b8873d5435606a5b433e910..56c4a09c862ca59f59ff684bcf9e6916486f6d9e 100644 (file)
@@ -283,8 +283,8 @@ int msdos_file_write(
                printk("msdos_file_write: mode = %07o\n",inode->i_mode);
                return -EINVAL;
        }
-       /* Must not harm system files */
-       if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return -EPERM;
+       /* system files are immutable */
+       if (IS_IMMUTABLE(inode)) return -EPERM;
 /*
  * ok, append may not work when many processes are writing at the same time
  * but so what. That way leads to madness anyway.
@@ -362,9 +362,8 @@ void msdos_truncate(struct inode *inode)
 {
        int cluster;
 
-       /* Must not harm system files */
        /* Why no return value?  Surely the disk could fail... */
-       if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return /* -EPERM */;
+       if (IS_IMMUTABLE(inode)) return /* -EPERM */;
        cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
        (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
        MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
index 3f4342e4848204c1a0f1079791febd799d9a3d0f..77d6a5c8163a58a85b0be4edbc8f7bd019a9fd03 100644 (file)
@@ -81,7 +81,9 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
 
        *check = 'n';
        *conversion = 'b';
-       *dotsOK =0;
+       /* Please leave dotsOK as 1, and contact Albert Cahalan if */
+       /* it causes any problems for you. <albert@ccs.neu.edu>    */
+       *dotsOK =1;  /* see note above, and report problems */
        *uid = current->uid;
        *gid = current->gid;
        *umask = current->fs->umask;
@@ -427,6 +429,8 @@ void msdos_read_inode(struct inode *inode)
                inode->i_nlink = 1;
                inode->i_size = CF_LE_L(raw_entry->size);
        }
+       if(raw_entry->attr & ATTR_SYS)
+               inode->i_flags |= S_IMMUTABLE;
        MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion,
            raw_entry->ext);
        MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
index 7d3299b804cd9b308f7bcecb47b7d15c5b459264..33ce37e197d31474e3b6d000ebc198e74ccd2245 100644 (file)
@@ -452,7 +452,7 @@ static int msdos_unlinkx(
                res = -EPERM;
                goto unlink_done;
        }
-       if (MSDOS_I(inode)->i_attrs & ATTR_SYS){
+       if (IS_IMMUTABLE(inode)){
                res = -EPERM;
                goto unlink_done;
        }
index e2f9c0e4d83ee78e0afea75dceae507f0c3fcd76..3b1aa1ad61c712cb143a6106d351343a517d6d90 100644 (file)
@@ -371,7 +371,7 @@ int open_namei(const char * pathname, int flag, int mode,
                        error = -EROFS;
                else {
                        dir->i_count++;         /* create eats the dir */
-                       if (dir->i_sb->dq_op)
+                       if (dir->i_sb && dir->i_sb->dq_op)
                                dir->i_sb->dq_op->initialize(dir, -1);
                        error = dir->i_op->create(dir, basename, namelen, mode, res_inode);
                        up(&dir->i_sem);
@@ -422,7 +422,7 @@ int open_namei(const char * pathname, int flag, int mode,
                        iput(inode);
                        return error;
                }
-               if (inode->i_sb->dq_op)
+               if (inode->i_sb && inode->i_sb->dq_op)
                        inode->i_sb->dq_op->initialize(inode, -1);
                newattrs.ia_size = 0;
                newattrs.ia_valid = ATTR_SIZE;
@@ -440,7 +440,7 @@ int open_namei(const char * pathname, int flag, int mode,
                put_write_access(inode);
        } else
                if (flag & FMODE_WRITE)
-                       if (inode->i_sb->dq_op)
+                       if (inode->i_sb && inode->i_sb->dq_op)
                                inode->i_sb->dq_op->initialize(inode, -1);
        *res_inode = inode;
        return 0;
@@ -473,7 +473,7 @@ int do_mknod(const char * filename, int mode, dev_t dev)
                return -EPERM;
        }
        dir->i_count++;
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        down(&dir->i_sem);
        error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
@@ -532,7 +532,7 @@ static int do_mkdir(const char * pathname, int mode)
                return -EPERM;
        }
        dir->i_count++;
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        down(&dir->i_sem);
        error = dir->i_op->mkdir(dir, basename, namelen, mode & 0777 & ~current->fs->umask);
@@ -586,7 +586,7 @@ static int do_rmdir(const char * name)
                iput(dir);
                return -EPERM;
        }
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        return dir->i_op->rmdir(dir,basename,namelen);
 }
@@ -636,7 +636,7 @@ static int do_unlink(const char * name)
                iput(dir);
                return -EPERM;
        }
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        return dir->i_op->unlink(dir,basename,namelen);
 }
@@ -680,7 +680,7 @@ static int do_symlink(const char * oldname, const char * newname)
                return -EPERM;
        }
        dir->i_count++;
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        down(&dir->i_sem);
        error = dir->i_op->symlink(dir,basename,namelen,oldname);
@@ -751,7 +751,7 @@ static int do_link(struct inode * oldinode, const char * newname)
                return -EPERM;
        }
        dir->i_count++;
-       if (dir->i_sb->dq_op)
+       if (dir->i_sb && dir->i_sb->dq_op)
                dir->i_sb->dq_op->initialize(dir, -1);
        down(&dir->i_sem);
        error = dir->i_op->link(oldinode, dir, basename, namelen);
@@ -839,7 +839,7 @@ static int do_rename(const char * oldname, const char * newname)
                return -EPERM;
        }
        new_dir->i_count++;
-       if (new_dir->i_sb->dq_op)
+       if (new_dir->i_sb && new_dir->i_sb->dq_op)
                new_dir->i_sb->dq_op->initialize(new_dir, -1);
        down(&new_dir->i_sem);
        error = old_dir->i_op->rename(old_dir, old_base, old_len, 
index 25aed5e958f3b93f6d9352b639650b879bc85a7e..7f38ed3534d9deac99928f5c158825e183ac0b6e 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -367,6 +367,7 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
        struct inode * inode;
        struct file * file;
        struct iattr newattrs;
+       int error;
 
        if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
                return -EBADF;
@@ -400,7 +401,16 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
                newattrs.ia_valid |= ATTR_MODE;
        }
        inode->i_dirt = 1;
-       return notify_change(inode, &newattrs);
+       if (inode->i_sb->dq_op) {
+               inode->i_sb->dq_op->initialize(inode, -1);
+               if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+                       return -EDQUOT;
+               error = notify_change(inode, &newattrs);
+               if (error)
+                       inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+       } else
+               error = notify_change(inode, &newattrs);
+       return error;
 }
 
 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
@@ -444,7 +454,15 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
                newattrs.ia_valid |= ATTR_MODE;
        }
        inode->i_dirt = 1;
-       error = notify_change(inode, &newattrs);
+       if (inode->i_sb->dq_op) {
+               inode->i_sb->dq_op->initialize(inode, -1);
+               if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+                       return -EDQUOT;
+               error = notify_change(inode, &newattrs);
+               if (error)
+                       inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+       } else
+               error = notify_change(inode, &newattrs);
        iput(inode);
        return(error);
 }
index 893a7ef974a208ace3118ea3e5d765743e41e30b..206929ac2242463ad810845a1fcb095e9fff73e5 100644 (file)
@@ -404,6 +404,7 @@ struct super_block *UMSDOS_read_super(
        printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
                ,UMSDOS_VERSION,UMSDOS_RELEASE);
        if (sb != NULL){
+               MSDOS_SB(sb)->dotsOK = 0;  /* disable hidden==dotfile */
                sb->s_op = &umsdos_sops;
                PRINTK (("umsdos_read_super %p\n",sb->s_mounted));
                umsdos_setup_dir_inode (sb->s_mounted);
index 9a4e87617379f90b2bfcbc9f7c11c1482c80dfb4..688f9bd4cb6668a7804e29a4eba8ce9680c9a69d 100644 (file)
@@ -9,17 +9,62 @@
  * in <asm/page.h> (currently 8192).
  */
 
-#define invalidate_all() \
-__asm__ __volatile__( \
-       "lda $16,-2($31)\n\t" \
-       ".long 51" \
-       : : :"$1", "$16", "$17", "$22","$23","$24","$25")
-
-#define invalidate() \
-__asm__ __volatile__( \
-       "lda $16,-1($31)\n\t" \
-       ".long 51" \
-       : : :"$1", "$16", "$17", "$22","$23","$24","$25")
+extern void tbi(long type, ...);
+
+#define tbisi(x)       tbi(1,(x))
+#define tbisd(x)       tbi(2,(x))
+#define tbis(x)                tbi(3,(x))
+#define tbiap()                tbi(-1)
+#define tbia()         tbi(-2)
+
+/*
+ * Invalidate current user mapping.
+ */
+static inline void invalidate(void)
+{
+       tbiap();
+}
+
+/*
+ * Invalidate everything (kernel mapping may also have
+ * changed due to vmalloc/vfree)
+ */
+static inline void invalidate_all(void)
+{
+       tbia();
+}
+
+/*
+ * Invalidate a specified user mapping
+ */
+static inline void invalidate_mm(struct mm_struct *mm)
+{
+       tbiap();
+}
+
+/*
+ * Page-granular invalidate.
+ *
+ * do a tbisd (type = 2) normally, and a tbis (type = 3)
+ * if it is an executable mapping.  We want to avoid the
+ * itlb invalidate, because that potentially also does a
+ * icache invalidate. 
+ */
+static inline void invalidate_page(struct vm_area_struct *vma,
+       unsigned long addr)
+{
+       tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+}
+
+/*
+ * Invalidate a specified range of user mapping: on the
+ * alpha we invalidate the whole user tlb
+ */
+static inline void invalidate_range(struct mm_struct *mm,
+       unsigned long start, unsigned long end)
+{
+       tbiap();
+}
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -143,9 +188,9 @@ extern pmd_t * __bad_pagetable(void);
 
 extern unsigned long __zero_page(void);
 
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
+#define BAD_PAGETABLE  __bad_pagetable()
+#define BAD_PAGE       __bad_page()
+#define ZERO_PAGE      0xfffffc000030A000
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR                   (8*sizeof(unsigned long))
index 892a7a631d3547cf6a756e1f88bc978df12b6581..98893a082f6448ee47ede855692116feffdcef61 100644 (file)
@@ -46,6 +46,9 @@ struct thread_struct {
        0, 0, 0, \
 }
 
+#define alloc_kernel_stack()    get_free_page(GFP_KERNEL)
+#define free_kernel_stack(page) free_page((page))
+
 #include <asm/ptrace.h>
 
 /*
index ae5c30e792da07ebd1a057cd8217d3383a1accfb..4822df44125a452855d2b64f4bd0c322012cc371 100644 (file)
@@ -102,6 +102,9 @@ struct ltchars {
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
 
+#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+
 /* Used for packet mode */
 #define TIOCPKT_DATA            0
 #define TIOCPKT_FLUSHREAD       1
index f949e0bc1edb8c55cb2e669a4b4c63a297dacb28..e7b6d3e2a1431bb6104a8dbcc26b09769970b8db 100644 (file)
@@ -110,8 +110,25 @@ static void check_hlt(void)
        printk("Ok.\n");
 }
 
+static void check_tlb(void)
+{
+       /*
+        * The 386 chips don't support TLB finegrained invalidation.
+        * They will fault when they hit a invlpg instruction.
+        */
+       if (x86 == 3) {
+#if defined(CONFIG_M486) || defined(CONFIG_M586)
+               printk("CPU is a 386 and this kernel was compiled for 486 or better.\n");
+               printk("Giving up.\n");
+               for (;;) ;
+#endif
+               return;
+       }
+}
+
 static void check_bugs(void)
 {
+       check_tlb();
        check_fpu();
        check_hlt();
        system_utsname.machine[1] = '0' + x86;
index 597c7bd104b03eb869f47c8f9214580c55da14b7..b1d5e33073587832847db2092c6c83ae21e97442 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _I386_PGTABLE_H
 #define _I386_PGTABLE_H
 
+#include <linux/config.h>
+
 /*
  * Define USE_PENTIUM_MM if you want the 4MB page table optimizations.
  * This works only on a intel Pentium.
@@ -33,7 +35,7 @@
 #define __invalidate() \
 __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 
-#ifdef __i486__
+#ifdef CONFIG_M486
 #define __invalidate_one(addr) \
 __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
 #else
@@ -51,10 +53,10 @@ static inline void invalidate_mm(struct mm_struct *mm)
                __invalidate();
 }
 
-static inline void invalidate_page(struct mm_struct *mm,
+static inline void invalidate_page(struct vm_area_struct *vma,
        unsigned long addr)
 {
-       if (mm == current->mm)
+       if (vma->vm_mm == current->mm)
                __invalidate_one(addr);
 }
 
@@ -87,7 +89,7 @@ static inline void invalidate_mm(struct mm_struct *mm)
        invalidate();
 }
 
-static inline void invalidate_page(struct mm_struct *mm,
+static inline void invalidate_page(struct vm_area_struct *vma,
        unsigned long addr)
 {
        invalidate();
index b540134a6bf95d5a49ac5ad684224ad6065412a3..dea7827b9e257d3c5a7418f657422b2d879ef5cf 100644 (file)
@@ -124,6 +124,9 @@ struct thread_struct {
        NULL, 0, 0, 0, 0 /* vm86_info */ \
 }
 
+#define alloc_kernel_stack()    get_free_page(GFP_KERNEL)
+#define free_kernel_stack(page) free_page((page))
+
 static inline void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp)
 {
        regs->cs = USER_CS;
index 867b597f3a3c979f16174cd73f483a9f2649f3a1..e54a7cd7ff149e20e7c0da3daf60c90d7c9488a6 100644 (file)
@@ -55,6 +55,9 @@
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
 
+#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+
 /* Used for packet mode */
 #define TIOCPKT_DATA            0
 #define TIOCPKT_FLUSHREAD       1
diff --git a/include/asm-mips/a.out.h b/include/asm-mips/a.out.h
new file mode 100644 (file)
index 0000000..c50f2aa
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_MIPS_A_OUT_H
+#define __ASM_MIPS_A_OUT_H
+
+struct exec
+{
+  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
+  unsigned a_text;             /* length of text, in bytes */
+  unsigned a_data;             /* length of data, in bytes */
+  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;             /* length of symbol table data in file, in bytes */
+  unsigned a_entry;            /* start address */
+  unsigned a_trsize;           /* length of relocation info for text, in bytes */
+  unsigned a_drsize;           /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP      TASK_SIZE
+
+#endif
+
+#endif /* __ASM_MIPS_A_OUT_H */
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h
new file mode 100644 (file)
index 0000000..7fc2bb9
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * include/asm-mips/asm.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ *
+ * Some usefull macros for MIPS assembler code
+ *
+ * Some of the routines below contain useless nops that will be optimized
+ * away by gas in -O mode. These nops are however required to fill delay
+ * slots in noreorder mode.
+ */
+#ifndef        __ASM_ASM_H
+#define        __ASM_ASM_H
+
+#include <linux/config.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+
+#ifndef CAT
+#ifdef __STDC__
+#define __CAT(str1,str2) str1##str2
+#else
+#define __CAT(str1,str2) str1/**/str2
+#endif
+#define CAT(str1,str2) __CAT(str1,str2)
+#endif
+
+/*
+ * Macros to handle different pointer sizes for 32/64-bit code
+ */
+#if __mips == 3
+#define PTR    .quad
+#define PTRSIZE        8
+#define PTRLOG 3
+#define lp     ld
+#else
+#define PTR    .word
+#define PTRSIZE        4
+#define PTRLOG 2
+#define lp     lw
+#endif
+
+/*
+ * ELF specific declarations
+ */
+#ifdef __ELF__
+#define TYPE(symbol,_type)                              \
+                       .type   symbol,@_type
+#define SIZE(symbol,_size)                              \
+                       .size   symbol,_size
+#else
+#define TYPE(symbol,type)
+#define SIZE(symbol,size)
+#endif
+
+/*
+ * PIC specific declarations
+ * Not used for the kernel but here seems to be the right place.
+ */
+#ifdef __PIC__
+#define CPRESTORE(register)                             \
+                       .cprestore register
+#define CPADD(register)                                 \
+                       .cpadd  register
+#define CPLOAD(register)                                \
+                       .cpload register
+#else
+#define CPRESTORE(register)
+#define CPADD(register)
+#define CPLOAD(register)
+#endif
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define        LEAF(symbol)                                    \
+                       .globl  symbol;                 \
+                       .align  2;                      \
+                       TYPE(symbol,function);          \
+                       .ent    symbol,0;               \
+symbol:                        .frame  sp,0,ra
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define        NESTED(symbol, framesize, rpc)                  \
+                       .globl  symbol;                 \
+                       .align  2;                      \
+                       TYPE(symbol,function);          \
+                       .ent    symbol,0;               \
+symbol:                        .frame  sp, framesize, rpc
+
+/*
+ * END - mark end of function
+ */
+#define        END(function)                                   \
+                       .end    function;               \
+                       SIZE(function,.-function)
+
+/*
+ * EXPORT - export definition of symbol
+ */
+#define        EXPORT(symbol)                                  \
+                       .globl  symbol;                 \
+symbol:
+
+/*
+ * ABS - export absolute symbol
+ */
+#define        ABS(symbol,value)                               \
+                       .globl  symbol;                 \
+symbol                 =       value
+
+#define        PANIC(msg)                                      \
+                       la      a0,8f;                  \
+                       jal     panic;                  \
+                       nop;                            \
+9:                     b       9b;                     \
+                       nop;                            \
+                       TEXT(msg)
+
+/*
+ * Print formated string
+ */
+#define PRINT(string)                                   \
+                       la      a0,8f;                  \
+                       jal     printk;                 \
+                       nop;                            \
+                       TEXT(string)
+
+#define        TEXT(msg)                                       \
+                       .data;                          \
+8:                     .asciiz msg;                    \
+                       .text
+
+/*
+ * Build text tables
+ */
+#define TTABLE(string)                                  \
+               .text;                                  \
+               .word   1f;                             \
+               .data;                                  \
+1:             .asciz  string;                         \
+               .text;
+
+/*
+ * Move to kernel mode and disable interrupts
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ * Use with .set noat!
+ * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
+ * means that another three instructions will be executed with interrupts
+ * disabled.
+ */
+#define CLI                                             \
+               mfc0    AT,CP0_STATUS;                  \
+               li      t0,ST0_CU0|0x1f;                \
+               or      AT,t0;                          \
+               xori    AT,0x1f;                        \
+               mtc0    AT,CP0_STATUS;                  \
+
+/*
+ * Move to kernel mode and enable interrupts
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ * Use with .set noat!
+ * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
+ * means that another three instructions will be executed with interrupts
+ * disabled.  Arch/mips/kernel/r4xx0.S makes use of this fact.
+ */
+#define STI                                             \
+               mfc0    AT,CP0_STATUS;                  \
+               li      t0,ST0_CU0|0x1f;                \
+               or      AT,t0;                          \
+               xori    AT,0x1e;                        \
+               mtc0    AT,CP0_STATUS;                  \
+
+/*
+ * Special nop to fill load delay slots
+ */
+#ifndef __R4000__
+#define NOP     nop
+#else
+#define NOP
+#endif
+
+/*
+ * Return from exception
+ */
+#if defined (CONFIG_CPU_R3000)
+#define ERET rfe
+#elif defined (CONFIG_CPU_R4X00) || defined (CONFIG_CPU_R4600)
+#define ERET                                            \
+               .set    mips3;                          \
+               eret;                                   \
+               .set    mips0
+#else
+#error "Implement ERET macro!"
+#endif
+
+/*
+ * R8000/R10000 (MIPS ISA IV) pref instruction.
+ * Use with .set noreorder only!
+ */
+#if defined (CONFIG_CPU_R8000) || defined(CONFIG_CPU_R10000)
+#define PREF(hint,addr)                                 \
+               pref    hint,addr
+#define PREFX(hint,addr)                                \
+               prefx   hint,addr
+#else
+#define PREF
+#define PREFX
+#endif
+
+/*
+ * R8000/R10000 (MIPS ISA IV) movn/movz instructions and
+ * equivalents for old CPUs. Use with .set noreorder only!
+ */
+#if defined (CONFIG_CPU_R8000) || defined (CONFIG_CPU_R10000)
+#define MOVN(rd,rs,rt)                                  \
+               movn    rd,rs,rt
+#define MOVZ(rd,rs,rt)                                  \
+               movz    rd,rs,rt
+#elif defined (CONFIG_CPU_R4000) || defined (CONFIG_CPU_R6000)
+#define MOVN(rd,rs,rt)                                  \
+               bnezl   rt,9f                           \
+               move    rd,rs                           \
+9:
+#define MOVZ(rd,rs,rt)                                  \
+               beqzl   rt,9f                           \
+               movz    rd,rt                           \
+9:
+#else /* R2000, R3000 */
+#define MOVN(rd,rs,rt)                                  \
+               beqz    rt,9f                           \
+               nop                                     \
+               move    rd,rs                           \
+9:
+#define MOVZ(rd,rs,rt)                                  \
+               bneqz   rt,9f                           \
+               nop                                     \
+               movz    rd,rt                           \
+9:
+#endif
+
+#endif /* __ASM_ASM_H */
index 7a98f59b86c7270205273c1a17d1cf0e288935d4..2f204b54a5c2f67f08ea9e08e24311412aab0aaa 100644 (file)
 #ifndef __ASM_MIPS_BITOPS_H
 #define __ASM_MIPS_BITOPS_H
 
-#ifdef __R4000__
+#if __mips > 1
 
+/*
+ * These functions for MIPS ISA >= 2 are interrupt and SMP proof and
+ * interrupt friendly
+ */
 #include <asm/mipsregs.h>
 
 /*
@@ -62,14 +66,19 @@ extern __inline__ int change_bit(int nr, void *addr)
        return retval;
 }
 
-#else /* !defined(__R4000__) */
+#else /* __mips <= 1 */
 
+/*
+ * These functions are only used for MIPS ISA 1 CPUs.  Since I don't
+ * believe that someone ever will run Linux/SMP on such a beast I don't
+ * worry about making them SMP proof.
+ */
 #include <asm/system.h>
 
 #ifdef __KERNEL__
 /*
- * Only disable interrupt for kernelmode stuff to keep some
- * usermode stuff alive
+ * Only disable interrupt for kernel mode stuff to keep usermode stuff
+ * that dares to use kernel include files alive.
  */
 #define __flags unsigned long flags
 #define __cli() cli()
@@ -133,17 +142,11 @@ extern __inline__ int change_bit(int nr, void * addr)
 #undef __save_flags(x)
 #undef __restore_flags(x)
 
-#endif /* !defined(__R4000__) */
+#endif /* __mips <= 1 */
 
 extern __inline__ int test_bit(int nr, const void *addr)
 {
-       int     mask;
-       unsigned long   *a;
-
-       a = addr;
-       addr += nr >> 5;
-       mask = 1 << (nr & 0x1f);
-       return ((mask & *a) != 0);
+       return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
 }
 
 extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
@@ -227,19 +230,17 @@ extern __inline__ unsigned long ffz(unsigned long word)
        __asm__ __volatile__ (
                ".set\tnoreorder\n\t"
                ".set\tnoat\n\t"
-               "li\t%2,1\n"
+               "move\t%0,$0\n"
                "1:\tand\t$1,%2,%1\n\t"
-               "beq\t$0,$1,2f\n\t"
-               "sll\t%2,%2,1\n\t"
-               "bne\t$0,%2,1b\n\t"
-               "add\t%0,%0,1\n\t"
+               "beqz\t$1,2f\n\t"
+               "sll\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,1\n\t"
                ".set\tat\n\t"
                ".set\treorder\n"
                "2:\n\t"
-               : "=r" (__res), "=r" (word), "=r" (mask)
-               : "1" (~(word)),
-                 "2" (mask),
-                 "0" (0)
+               : "=r" (__res), "=r" (mask)
+               : "r" (word), "1" (mask)
                : "$1");
 
        return __res;
index cf091b0a5ba1ab99b21b31ab825729ff4aceb88b..9a10309ac0271c8a906c1b1d9081525b527cb6ae 100644 (file)
  * License.  See the file README.legal in the main directory of this archive
  * for more details.
  */
-
 #ifndef __ASM_MIPS_BOOTINFO_H
 #define __ASM_MIPS_BOOTINFO_H
 
 /*
- * Valid values for machtype field
+ * Valid machtype values
  */
-#define MACH_UNKNOWN           0               /* whatever... */
-#define MACH_DESKSTATION_TYNE  1               /* Deskstation Tyne    */
-#define MACH_ACER_PICA_61      2               /* Acer PICA-61 (PICA1) */
-#define MACH_MIPS_MAGNUM_4000  3               /* Mips Magnum 4000 (aka RC4030) */
+#define MACH_UNKNOWN           0               /* whatever...               */
+#define MACH_DESKSTATION_RPC44  1               /* Deskstation rPC44         */
+#define MACH_DESKSTATION_TYNE  2               /* Deskstation Tyne          */
+#define MACH_ACER_PICA_61      3               /* Acer PICA-61 (PICA1)      */
+#define MACH_MIPS_MAGNUM_4000  4               /* Mips Magnum 4000 "RC4030" */
+#define MACH_OLIVETTI_M700      5               /* Olivetti M700 */
+#define MACH_LAST               5
+
+#define MACH_NAMES { "unknown", "Deskstation rPC44", "Deskstation Tyne", \
+       "Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" }
 
 /*
- * Valid values for cputype field
+ * Valid cputype values
  */
 #define CPU_UNKNOWN            0
 #define CPU_R2000              1
 #define CPU_R6000A             18
 #define CPU_R8000              19
 #define CPU_R10000             20
+#define CPU_LAST                20
 
-#define CPU_NAMES { "UNKNOWN", "R2000", "R3000", "R3000A", "R3041", "R3051", \
+#define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \
         "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC",         \
         "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000",          \
         "R6000A", "R8000", "R10000" }
 
 #define CL_SIZE      (80)
 
-#ifndef __ASSEMBLY__
+#ifndef __LANGUAGE_ASSEMBLY__
 
 /*
  * Some machine parameters passed by MILO. Note that bootinfo
@@ -68,8 +74,15 @@ struct drive_info_struct {
        };
 
 struct bootinfo {
-       unsigned long machtype;                 /* machine type */
-       unsigned long cputype;                  /* system CPU & FPU */
+       /*
+        * machine type
+        */
+       unsigned long machtype;
+
+       /*
+        * system CPU & FPU
+        */
+       unsigned long cputype;
 
        /*
         * Installed RAM
@@ -101,7 +114,7 @@ struct bootinfo {
        /*
         * Ramdisk Info
         */
-       unsigned long ramdisk_size;             /* ramdisk size in 1024 byte blocks */
+       unsigned long ramdisk_flags;            /* ramdisk flags */
        unsigned long ramdisk_base;             /* address of the ram disk in mem */
 
        /*
@@ -119,6 +132,83 @@ struct bootinfo {
   
 };
 
+#if 0
+/*
+ * New style bootinfo
+ *
+ * Add new tags only at the end of the enum; *never* remove any tags
+ * or you'll break compatibility!
+ */
+enum bi_tag {  
+       /*
+        * not a real tag
+        */
+       dummy,
+
+       /*
+        * machine type
+        */
+       machtype,
+
+       /*
+        * system CPU & FPU
+        */
+       cputype,
+
+       /*
+        * Installed RAM
+        */
+       memlower,
+       memupper,
+
+       /*
+        * Cache Sizes (0xffffffff = unknown)
+        */
+       icache_size,
+       icache_linesize,
+       dcache_size,
+       dcache_linesize,
+       scache_size,
+       scache_linesize,
+
+       /*
+        * TLB Info
+        */
+       tlb_entries,
+
+       /*
+        * DMA buffer size (Deskstation only)
+        */
+       dma_cache_size,
+       dma_cache_base,
+
+       /*
+        * Ramdisk Info
+        */
+       ramdisk_size,           /* ramdisk size in 1024 byte blocks */
+       ramdisk_base,           /* address of the ram disk in mem */
+
+       /*
+        * Boot flags for the kernel
+        */
+       mount_root_rdonly,
+       drive_info,
+
+       /*
+        * Video ram info (not in tty.h)
+        */
+       vram_base,              /* video ram base address */
+      
+       command_line            /* kernel command line parameters */
+  
+};
+
+typedef struct {
+       bi_tag          tag;
+       unsigned long   size;
+} tag;
+#endif
+
 extern struct bootinfo boot_info;
 
 /*
@@ -127,9 +217,10 @@ extern struct bootinfo boot_info;
  * are in the .data segment since the .bss segment is
  * cleared during startup.
  */
-#define BOOT_INFO { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"" }
+#define BOOT_INFO { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, {{0,}}, 0, "" }
+#define SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50}
 
-#else /* !__ASSEMBLY__ */
+#else /* !__LANGUAGE_ASSEMBLY__ */
 
 /*
  * Same structure, but as offsets for usage within assembler source.
@@ -151,9 +242,11 @@ extern struct bootinfo boot_info;
 #define OFFSET_BOOTINFO_DMA_CACHE_BASE    48
 #define OFFSET_BOOTINFO_RAMDISK_SIZE      52
 #define OFFSET_BOOTINFO_RAMDISK_BASE      56
-#define OFFSET_BOOTINFO_VRAM_BASE         60
-#define OFFSET_BOOTINFO_COMMAND_LINE      64
+#define OFFSET_BOOTINFO_MOUNT_RD_ONLY     60
+#define OFFSET_BOOTINFO_DRIVE_INFO        64
+#define OFFSET_BOOTINFO_VRAM_BASE         96
+#define OFFSET_BOOTINFO_COMMAND_LINE      100
 
-#endif /* __ASSEMBLY__ */
+#endif /* __LANGUAGE_ASSEMBLY__ */
 
 #endif /* __ASM_MIPS_BOOTINFO_H */
index f8120c10c9bc903cd8f732c9b61e8f2a634efa8b..3085c9c0c8ed9fd65a6f4d613f8f36631278f87e 100644 (file)
@@ -1,19 +1,22 @@
 #ifndef __ASM_MIPS_BYTEORDER_H
 #define __ASM_MIPS_BYTEORDER_H
 
+/*
+ * FIXME: Add big endian support
+ */
 #undef ntohl
 #undef ntohs
 #undef htonl
 #undef htons
 
-#ifdef MIPSEL
+#if defined (__MIPSEL__)
 #define __LITTLE_ENDIAN
 #define __LITTLE_ENDIAN_BITFIELD
-#elif MIPSEB
+#elif defined (__MIPSEB__)
 #define __BIG_ENDIAN
 #define __BIG_ENDIAN_BITFIELD
 #else
-#error "MIPS but neither MIPSEL nor MIPSEB?"
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
 #endif
 
 extern unsigned long int       ntohl(unsigned long int);
@@ -21,16 +24,18 @@ extern unsigned short int   ntohs(unsigned short int);
 extern unsigned long int       htonl(unsigned long int);
 extern unsigned short int      htons(unsigned short int);
 
-extern unsigned long int       __ntohl(unsigned long int);
-extern unsigned short int      __ntohs(unsigned short int);
-extern unsigned long int       __constant_ntohl(unsigned long int);
-extern unsigned short int      __constant_ntohs(unsigned short int);
+extern __inline__ unsigned long int    __ntohl(unsigned long int);
+extern __inline__ unsigned short int   __ntohs(unsigned short int);
+extern __inline__ unsigned long int    __constant_ntohl(unsigned long int);
+extern __inline__ unsigned short int   __constant_ntohs(unsigned short int);
 
 /*
  * The constant and non-constant versions here are the same.
  * Maybe I'll come up with an mips-optimized routine for the
  * non-constant ones (the constant ones don't need it: gcc
- * will optimize it to the correct constant)
+ * will optimize it to the correct constant).  Oh, and the
+ * big endian routines that are still missing will be fairly
+ * easy to write :-)
  */
 
 extern __inline__ unsigned long int
@@ -42,14 +47,11 @@ __ntohl(unsigned long int x)
                ((x & 0xff000000U) >> 24));
 }
 
-extern __inline__ unsigned long int
-__constant_ntohl(unsigned long int x)
-{
-       return (((x & 0x000000ffU) << 24) |
-               ((x & 0x0000ff00U) <<  8) |
-               ((x & 0x00ff0000U) >>  8) |
-               ((x & 0xff000000U) >> 24));
-}
+#define __constant_ntohl(x) \
+       ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+                            (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
+                            (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
+                            (((unsigned long int)(x) & 0xff000000U) >> 24)))
 
 extern __inline__ unsigned short int
 __ntohs(unsigned short int x)
@@ -58,12 +60,9 @@ __ntohs(unsigned short int x)
                ((x & 0xff00) >> 8));
 }
 
-extern __inline__ unsigned short int
-__constant_ntohs(unsigned short int x)
-{
-       return (((x & 0x00ff) << 8) |
-               ((x & 0xff00) >> 8));
-}
+#define __constant_ntohs(x) \
+       ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+                             (((unsigned short int)(x) & 0xff00) >> 8))) \
 
 #define __htonl(x) __ntohl(x)
 #define __htons(x) __ntohs(x)
index e33a3a4bd4527372c9cf0a10229f755fb134caa7..bd34ecec79ee06cabd2b807b9c03d788bce65c6e 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Written by Ralf Baechle,
  * Copyright (C) 1994 by Waldorf GMBH
- *
- * Defines for Risc/OS compatible cacheflush systemcall
  */
 #ifndef        __ASM_MIPS_CACHECTL
 #define        __ASM_MIPS_CACHECTL
 #define        DCACHE  (1<<1)          /* writeback and flush data cache */
 #define        BCACHE  (ICACHE|DCACHE) /* flush both caches              */
 
-#define CACHELINES      512             /* number of cachelines    */
-
 #ifdef __KERNEL__
-#ifndef __ASSEMBLY__
+#define CACHELINES      512    /* number of cachelines (kludgy)  */
+
+/*
+ * Cache Operations - for use by assembler code
+ */
+#define Index_Invalidate_I      0x00
+#define Index_Writeback_Inv_D   0x01
+#define Index_Load_Tag_D        0x05
+
+#ifndef __LANGUAGE_ASSEMBLY__
 
 extern int sys_cacheflush(void *addr, int nbytes, int cache);
 
-#endif
-#endif
+#endif /* !__LANGUAGE_ASSEMBLY__ */
+#endif   /* __KERNEL__ */
 #endif /* __ASM_MIPS_CACHECTL */
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
new file mode 100644 (file)
index 0000000..d9aff22
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * include/asm-mips/checksum.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_CHECKSUM_H
+#define __ASM_MIPS_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+
+/*
+ * the same as csum_partial, but copies from user space (but on the alpha
+ * we have just one address space, so this is identical to the above)
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+  
+/*
+ *     This is a version of ip_compute_csum() optimized for IP headers,
+ *     which always checksum on 4 octet boundaries.
+ *
+ *     By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ *     Arnt Gulbrandsen.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+                                         unsigned int ihl)
+{
+       unsigned short int sum;
+       unsigned long   dummy1, dummy2;
+
+       /*
+        * This is optimized for 32-bit MIPS processors.
+        * I tried it in plain C but the generated code looks to bad to
+        * use with old first generation MIPS CPUs.
+        * Using 64-bit code could even further improve these routines.
+        */
+       __asm__("
+       .set    noreorder
+       .set    noat
+       lw      %0,(%3)
+       subu    %1,4
+       blez    %1,2f
+       sll     %1,%4,2                 # delay slot
+       lw      %2,4(%3)
+       addu    %1,%3                   # delay slot
+       addu    %0,%2
+       sltu    $1,%0,%2
+       lw      %2,8(%3)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+       lw      %2,12(%3)
+       addu    %0,$1
+       addu    %0,%2
+       sltu    $1,%0,%2
+       addu    %0,$1
+1:     lw      %2,16(%3)
+       addu    %1,4
+       addu    %0,%2
+       sltu    $1,%0,%2
+       bne     %1,%3,1b
+       addu    %0,$1                   # delay slot
+       srl     $1,%0,16
+       addu    %0,$1
+       sltu    $1,%0,$1
+       addu    %0,$1
+       nor     %0,$0,%0
+       andi    %0,0xffff
+2:     .set    at
+       .set    reorder"
+       : "=r" (sum), "=r" (dummy1), "=r" (dummy2)
+       : "r" (iph), "r"(ihl)
+       : "$1");
+
+       return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+                                                  unsigned long daddr,
+                                                  unsigned short len,
+                                                  unsigned short proto,
+                                                  unsigned int sum)
+{
+    __asm__("
+       .set    noat
+       addu    %0,%2
+       sltu    $1,%0,%2
+       addu    %0,$1
+       addu    %0,%3
+       sltu    $1,%0,%3
+       addu    %0,$1
+       addu    %0,%4
+       sltu    $1,%0,%4
+       addu    %0,$1
+       srl     $1,%0,16
+       addu    %0,$1
+       sltu    $1,%0,$1
+       addu    %0,$1
+       nor     %0,$0,%0
+       andi    %0,0xffff
+       .set    at"
+       : "=r" (sum)
+       : "0" (daddr), "r"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
+       : "$1");
+
+       return (unsigned short)sum;
+}
+
+/*
+ *     Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned short int csum_fold(unsigned int sum)
+{
+    __asm__("
+       .set    noat
+       srl     $1,%0,16
+       addu    %0,$1
+       sltu    $1,%0,$1
+       nor     %0,$0,%0
+       andi    %0,0xffff
+       .set    at"
+       : "=r"(sum)
+       : "0" (sum)
+       : "$1");
+
+       return sum;
+}
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+    unsigned short int sum;
+
+    __asm__("
+       .set    noat
+       srl     $1,%0,16
+       addu    %0,$1
+       sltu    $1,%0,$1
+       nor     %0,$0,%0
+       andi    %0,0xffff
+       .set    at"
+       : "=r"(sum)
+       : "r" (csum_partial(buff, len, 0))
+       : "$1");
+
+       return sum;
+}
+
+#endif /* __ASM_MIPS_CHECKSUM_H */
index 14695804b63715ffb51d4c2e621e009815627fed..b35498dc1f97e2a818a41f95b75bf5a0f48e502a 100644 (file)
@@ -27,15 +27,16 @@ extern __inline__ void __delay(int loops)
 extern __inline__ void udelay(unsigned long usecs)
 {
        usecs *= 0x000010c6;            /* 2**32 / 1000000 */
-       __asm__("mul\t%0,%0,%1"
+       __asm__("multu\t%0,%1\n\t"
+               "mfhi\t%0"
                :"=r" (usecs)
                :"0" (usecs),"r" (loops_per_sec));
        __delay(usecs);
 }
 
 /*
- * 64-bit integers means we don't have to worry about overflow as
- * on some other architectures..
+ * The different variants for 32/64 bit are pure paranoia. The typical
+ * range of numbers that apprears for MIPS machines avoids overflows.
  */
 extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
 {
index 838861392aed6f66cb9fbd1152ffe683e7b010d4..bae845dd4cda3b51da34d30b3f83806a701b2c80 100644 (file)
@@ -3,6 +3,10 @@
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
  * and John Boyd, Nov. 1992.
+ *
+ * NOTE: all this is true *only* for ISA/EISA expansions on Mips boards
+ * and can only be used for expansion cards. Onboard DMA controller, such
+ * as the R4030 on Jazz boards behave totally different!
  */
 
 #ifndef __ASM_MIPS_DMA_H
 
 #define MAX_DMA_CHANNELS       8
 
-/* The maximum address that we can perform a DMA transfer to on this platform */
-#define MAX_DMA_ADDRESS      0x1000000
-
-/* The maximum address that we can perform a DMA transfer to on this platform */
+/*
+ * The maximum address that we can perform a DMA transfer to on this platform
+ * This discribes only the PC style part of the DMA logic like on Deskstations
+ * or Acer PICA but not the much more versatile DMA logic used for the
+ * local devices on Acer PICA or Mangnums.
+ */
 #define MAX_DMA_ADDRESS                0x1000000
 
 /* 8237 DMA controllers */
@@ -270,5 +276,10 @@ static __inline__ int get_dma_residue(unsigned int dmanr)
 extern int request_dma(unsigned int dmanr, const char * device_id);    /* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);      /* release it again */
 
+/*
+ * DMA memory allocation - formerly in include/linux/mm.h
+ */
+#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), \
+                                             0x80000000 + MAX_DMA_ADDRESS)
 
 #endif /* __ASM_MIPS_DMA_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
new file mode 100644 (file)
index 0000000..886c4e8
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ASM_MIPS_ELF_H
+#define __ASM_MIPS_ELF_H
+
+/*
+ * ELF register definitions
+ * This is "make it compile" stuff!
+ */
+#define ELF_NGREG      32
+#define ELF_NFPREG     32
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#endif /* __ASM_MIPS_ELF_H */
diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h
new file mode 100644 (file)
index 0000000..f31e2b1
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * include/asm-mips/errno.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_ERRNO_H
+#define __ASM_MIPS_ERRNO_H
+
+/*
+ * These error numbers are intended to be MIPS ABI compatible
+ */
+#define        EPERM            1      /* Operation not permitted */
+#define        ENOENT           2      /* No such file or directory */
+#define        ESRCH            3      /* No such process */
+#define        EINTR            4      /* Interrupted system call */
+#define        EIO              5      /* I/O error */
+#define        ENXIO            6      /* No such device or address */
+#define        E2BIG            7      /* Arg list too long */
+#define        ENOEXEC          8      /* Exec format error */
+#define        EBADF            9      /* Bad file number */
+#define        ECHILD          10      /* No child processes */
+#define        EAGAIN          11      /* Try again */
+#define        ENOMEM          12      /* Out of memory */
+#define        EACCES          13      /* Permission denied */
+#define        EFAULT          14      /* Bad address */
+#define        ENOTBLK         15      /* Block device required */
+#define        EBUSY           16      /* Device or resource busy */
+#define        EEXIST          17      /* File exists */
+#define        EXDEV           18      /* Cross-device link */
+#define        ENODEV          19      /* No such device */
+#define        ENOTDIR         20      /* Not a directory */
+#define        EISDIR          21      /* Is a directory */
+#define        EINVAL          22      /* Invalid argument */
+#define        ENFILE          23      /* File table overflow */
+#define        EMFILE          24      /* Too many open files */
+#define        ENOTTY          25      /* Not a typewriter */
+#define        ETXTBSY         26      /* Text file busy */
+#define        EFBIG           27      /* File too large */
+#define        ENOSPC          28      /* No space left on device */
+#define        ESPIPE          29      /* Illegal seek */
+#define        EROFS           30      /* Read-only file system */
+#define        EMLINK          31      /* Too many links */
+#define        EPIPE           32      /* Broken pipe */
+#define        EDOM            33      /* Math argument out of domain of func */
+#define        ERANGE          34      /* Math result not representable */
+#define        ENOMSG          35      /* No message of desired type */
+#define        EIDRM           36      /* Identifier removed */
+#define        ECHRNG          37      /* Channel number out of range */
+#define        EL2NSYNC        38      /* Level 2 not synchronized */
+#define        EL3HLT          39      /* Level 3 halted */
+#define        EL3RST          40      /* Level 3 reset */
+#define        ELNRNG          41      /* Link number out of range */
+#define        EUNATCH         42      /* Protocol driver not attached */
+#define        ENOCSI          43      /* No CSI structure available */
+#define        EL2HLT          44      /* Level 2 halted */
+#define        EDEADLK         45      /* Resource deadlock would occur */
+#define        ENOLCK          46      /* No record locks available */
+#define        EBADE           50      /* Invalid exchange */
+#define        EBADR           51      /* Invalid request descriptor */
+#define        EXFULL          52      /* Exchange full */
+#define        ENOANO          53      /* No anode */
+#define        EBADRQC         54      /* Invalid request code */
+#define        EBADSLT         55      /* Invalid slot */
+#define        EDEADLOCK       56      /* File locking deadlock error */
+#define        EBFONT          59      /* Bad font file format */
+#define        ENOSTR          60      /* Device not a stream */
+#define        ENODATA         61      /* No data available */
+#define        ETIME           62      /* Timer expired */
+#define        ENOSR           63      /* Out of streams resources */
+#define        ENONET          64      /* Machine is not on the network */
+#define        ENOPKG          65      /* Package not installed */
+#define        EREMOTE         66      /* Object is remote */
+#define        ENOLINK         67      /* Link has been severed */
+#define        EADV            68      /* Advertise error */
+#define        ESRMNT          69      /* Srmount error */
+#define        ECOMM           70      /* Communication error on send */
+#define        EPROTO          71      /* Protocol error */
+#define        EDOTDOT         73      /* RFS specific error */
+#define        EMULTIHOP       74      /* Multihop attempted */
+#define        EBADMSG         77      /* Not a data message */
+#define        ENAMETOOLONG    78      /* File name too long */
+#define        EOVERFLOW       79      /* Value too large for defined data type */
+#define        ENOTUNIQ        80      /* Name not unique on network */
+#define        EBADFD          81      /* File descriptor in bad state */
+#define        EREMCHG         82      /* Remote address changed */
+#define        ELIBACC         83      /* Can not access a needed shared library */
+#define        ELIBBAD         84      /* Accessing a corrupted shared library */
+#define        ELIBSCN         85      /* .lib section in a.out corrupted */
+#define        ELIBMAX         86      /* Attempting to link in too many shared libraries */
+#define        ELIBEXEC        87      /* Cannot exec a shared library directly */
+#define        EILSEQ          88      /* Illegal byte sequence */
+#define        ENOSYS          89      /* Function not implemented */
+#define        ELOOP           90      /* Too many symbolic links encountered */
+#define        ERESTART        91      /* Interrupted system call should be restarted */
+#define        ESTRPIPE        92      /* Streams pipe error */
+#define        ENOTEMPTY       93      /* Directory not empty */
+#define        EUSERS          94      /* Too many users */
+#define        ENOTSOCK        95      /* Socket operation on non-socket */
+#define        EDESTADDRREQ    96      /* Destination address required */
+#define        EMSGSIZE        97      /* Message too long */
+#define        EPROTOTYPE      98      /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     99      /* Protocol not available */
+#define        EPROTONOSUPPORT 120     /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 121     /* Socket type not supported */
+#define        EOPNOTSUPP      122     /* Operation not supported on transport endpoint */
+#define        EPFNOSUPPORT    123     /* Protocol family not supported */
+#define        EAFNOSUPPORT    124     /* Address family not supported by protocol */
+#define        EADDRINUSE      125     /* Address already in use */
+#define        EADDRNOTAVAIL   126     /* Cannot assign requested address */
+#define        ENETDOWN        127     /* Network is down */
+#define        ENETUNREACH     128     /* Network is unreachable */
+#define        ENETRESET       129     /* Network dropped connection because of reset */
+#define        ECONNABORTED    130     /* Software caused connection abort */
+#define        ECONNRESET      131     /* Connection reset by peer */
+#define        ENOBUFS         132     /* No buffer space available */
+#define        EISCONN         133     /* Transport endpoint is already connected */
+#define        ENOTCONN        134     /* Transport endpoint is not connected */
+#define        EUCLEAN         135     /* Structure needs cleaning */
+#define        ENOTNAM         137     /* Not a XENIX named type file */
+#define        ENAVAIL         138     /* No XENIX semaphores available */
+#define        EISNAM          139     /* Is a named type file */
+#define        EREMOTEIO       140     /* Remote I/O error */
+#define EINIT          141     /* Reserved */
+#define EREMDEV                142     /* Error 142 */
+#define        ESHUTDOWN       143     /* Cannot send after transport endpoint shutdown */
+#define        ETOOMANYREFS    144     /* Too many references: cannot splice */
+#define        ETIMEDOUT       145     /* Connection timed out */
+#define        ECONNREFUSED    146     /* Connection refused */
+#define        EHOSTDOWN       147     /* Host is down */
+#define        EHOSTUNREACH    148     /* No route to host */
+#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
+#define        EALREADY        149     /* Operation already in progress */
+#define        EINPROGRESS     150     /* Operation now in progress */
+#define        ESTALE          151     /* Stale NFS file handle */
+#define ECANCELED      158     /* AIO operation canceled */
+#define        EDQUOT          1133    /* Quota exceeded */
+#define ENFSREMOTE     1134    /* ??? */
+
+#endif /* __ASM_MIPS_ERRNO_H */
diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h
new file mode 100644 (file)
index 0000000..a524af6
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __ASM_MIPS_FCNTL_H
+#define __ASM_MIPS_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE      0x0003
+#define O_RDONLY       0x0000
+#define O_WRONLY       0x0001
+#define O_RDWR         0x0002
+#define O_APPEND       0x0008
+#define O_SYNC         0x0010
+#define O_NONBLOCK     0x0080
+#define O_CREAT         0x0100 /* not fcntl */
+#define O_TRUNC                0x0200  /* not fcntl */
+#define O_EXCL         0x0400  /* not fcntl */
+#define O_NOCTTY       0x0800  /* not fcntl */
+#define FASYNC         0x1000  /* fcntl, for BSD compatibility */
+
+#define O_NDELAY       O_NONBLOCK
+
+#define F_DUPFD                0       /* dup */
+#define F_GETFD                1       /* get f_flags */
+#define F_SETFD                2       /* set f_flags */
+#define F_GETFL                3       /* more flags (cloexec) */
+#define F_SETFL                4
+#define F_GETLK                14
+#define F_SETLK                6
+#define F_SETLKW       7
+
+#define F_SETOWN       24      /*  for sockets. */
+#define F_GETOWN       23      /*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK                0
+#define F_WRLCK                1
+#define F_UNLCK                2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK                4       /* or 3 */
+#define F_SHLCK                8       /* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH                1       /* shared lock */
+#define LOCK_EX                2       /* exclusive lock */
+#define LOCK_NB                4       /* or'd with one of the above to prevent                XXXXXXXXXXXXXXXXXX
+                                  blocking */
+#define LOCK_UN                8       /* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX                1
+#define F_FLOCK                2
+#endif /* __KERNEL__ */
+
+typedef struct flock {
+       short l_type;
+       short l_whence;
+       off_t l_start;
+       off_t l_len;
+       long  l_sysid;                  /* XXXXXXXXXXXXXXXXXXXXXXXXX */
+       pid_t l_pid;
+       long  pad[4];                   /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */
+} flock_t;
+
+#endif /* __ASM_MIPS_FCNTL_H */
index 911276c1a4a18d11dc1db81d7e93184753c40724..cae3b112a321bb0efefa1da6b711d766c7614707 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/vector.h>
 
 #define fd_inb(port)                   feature->fd_inb(port)
-#define fd_outb(port,value)            feature->fd_outb(port,value)
+#define fd_outb(value,port)            feature->fd_outb(value,port)
 
 #define fd_enable_dma()                        feature->fd_enable_dma()
 #define fd_disable_dma()               feature->fd_disable_dma()
@@ -36,6 +36,7 @@
                                            "floppy")
 #define fd_free_irq()           free_irq(FLOPPY_IRQ);
 
+#define MAX_BUFFER_SECTORS 24
 #define virtual_dma_init()                                              \
         if (boot_info.machtype == MACH_ACER_PICA_61 ||                  \
             boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||              \
diff --git a/include/asm-mips/fpregdef.h b/include/asm-mips/fpregdef.h
new file mode 100644 (file)
index 0000000..b942b18
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Definitions for the FPU register names
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_FPREGDEF_H
+#define __ASM_MIPS_FPREGDEF_H
+
+/*
+ * These definitions only cover the R3000-ish 16/32 register model.
+ * But we're trying to be R3000 friendly anyway ...
+ */
+#define fv0    $f0      /* return value */
+#define fv0f   $f1
+#define fv1    $f2
+#define fv1f   $f3
+#define fa0    $f12     /* argument registers */
+#define fa0f   $f13
+#define fa1    $f14
+#define fa1f   $f15
+#define ft0    $f4      /* caller saved */
+#define ft0f   $f5
+#define ft1    $f6
+#define ft1f   $f7
+#define ft2    $f8
+#define ft2f   $f9
+#define ft3    $f10
+#define ft3f   $f11
+#define ft4    $f16
+#define ft4f   $f17
+#define ft5    $f18
+#define ft5f   $f19
+#define fs0    $f20     /* callee saved */
+#define fs0f   $f21
+#define fs1    $f22
+#define fs1f   $f23
+#define fs2    $f24
+#define fs2f   $f25
+#define fs3    $f26
+#define fs3f   $f27
+#define fs4    $f28
+#define fs4f   $f29
+#define fs5    $f30
+#define fs5f   $f31
+
+#define fcr31  $31      /* FPU status register */
+
+#endif /* !defined (__ASM_MIPS_FPREGDEF_H) */
diff --git a/include/asm-mips/gdb-stub.h b/include/asm-mips/gdb-stub.h
new file mode 100644 (file)
index 0000000..d85ce07
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ *  include/asm-mips/gdb-stub.h
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ */
+
+#ifndef __ASM_MIPS_GDB_STUB_H
+#define __ASM_MIPS_GDB_STUB_H
+
+
+/*
+ * important register numbers
+ */
+
+#define REG_EPC                        37
+#define REG_FP                 72
+#define REG_SP                 29
+
+/*
+ * Stack layout for the GDB exception handler
+ * Derived from the stack layout described in asm-mips/stackframe.h
+ *
+ * The first PTRSIZE*5 bytes are argument save space for C subroutines.
+ */
+#define NUMREGS                        90
+
+#define GDB_FR_REG0            (PTRSIZE*5)                     /* 0 */
+#define GDB_FR_REG1            ((GDB_FR_REG0) + 4)             /* 1 */
+#define GDB_FR_REG2            ((GDB_FR_REG1) + 4)             /* 2 */
+#define GDB_FR_REG3            ((GDB_FR_REG2) + 4)             /* 3 */
+#define GDB_FR_REG4            ((GDB_FR_REG3) + 4)             /* 4 */
+#define GDB_FR_REG5            ((GDB_FR_REG4) + 4)             /* 5 */
+#define GDB_FR_REG6            ((GDB_FR_REG5) + 4)             /* 6 */
+#define GDB_FR_REG7            ((GDB_FR_REG6) + 4)             /* 7 */
+#define GDB_FR_REG8            ((GDB_FR_REG7) + 4)             /* 8 */
+#define GDB_FR_REG9            ((GDB_FR_REG8) + 4)             /* 9 */
+#define GDB_FR_REG10           ((GDB_FR_REG9) + 4)             /* 10 */
+#define GDB_FR_REG11           ((GDB_FR_REG10) + 4)            /* 11 */
+#define GDB_FR_REG12           ((GDB_FR_REG11) + 4)            /* 12 */
+#define GDB_FR_REG13           ((GDB_FR_REG12) + 4)            /* 13 */
+#define GDB_FR_REG14           ((GDB_FR_REG13) + 4)            /* 14 */
+#define GDB_FR_REG15           ((GDB_FR_REG14) + 4)            /* 15 */
+#define GDB_FR_REG16           ((GDB_FR_REG15) + 4)            /* 16 */
+#define GDB_FR_REG17           ((GDB_FR_REG16) + 4)            /* 17 */
+#define GDB_FR_REG18           ((GDB_FR_REG17) + 4)            /* 18 */
+#define GDB_FR_REG19           ((GDB_FR_REG18) + 4)            /* 19 */
+#define GDB_FR_REG20           ((GDB_FR_REG19) + 4)            /* 20 */
+#define GDB_FR_REG21           ((GDB_FR_REG20) + 4)            /* 21 */
+#define GDB_FR_REG22           ((GDB_FR_REG21) + 4)            /* 22 */
+#define GDB_FR_REG23           ((GDB_FR_REG22) + 4)            /* 23 */
+#define GDB_FR_REG24           ((GDB_FR_REG23) + 4)            /* 24 */
+#define GDB_FR_REG25           ((GDB_FR_REG24) + 4)            /* 25 */
+#define GDB_FR_REG26           ((GDB_FR_REG25) + 4)            /* 26 */
+#define GDB_FR_REG27           ((GDB_FR_REG26) + 4)            /* 27 */
+#define GDB_FR_REG28           ((GDB_FR_REG27) + 4)            /* 28 */
+#define GDB_FR_REG29           ((GDB_FR_REG28) + 4)            /* 29 */
+#define GDB_FR_REG30           ((GDB_FR_REG29) + 4)            /* 30 */
+#define GDB_FR_REG31           ((GDB_FR_REG30) + 4)            /* 31 */
+       
+/*
+ * Saved special registers
+ */
+#define GDB_FR_STATUS          ((GDB_FR_REG31) + 4)            /* 32 */
+#define GDB_FR_LO              ((GDB_FR_STATUS) + 4)           /* 33 */
+#define GDB_FR_HI              ((GDB_FR_LO) + 4)               /* 34 */
+#define GDB_FR_BADVADDR                ((GDB_FR_HI) + 4)               /* 35 */
+#define GDB_FR_CAUSE           ((GDB_FR_BADVADDR) + 4)         /* 36 */
+#define GDB_FR_EPC             ((GDB_FR_CAUSE) + 4)            /* 37 */
+
+/*
+ * Saved floating point registers
+ */
+#define GDB_FR_FPR0            ((GDB_FR_EPC) + 4)              /* 38 */
+#define GDB_FR_FPR1            ((GDB_FR_FPR0) + 4)             /* 39 */
+#define GDB_FR_FPR2            ((GDB_FR_FPR1) + 4)             /* 40 */
+#define GDB_FR_FPR3            ((GDB_FR_FPR2) + 4)             /* 41 */
+#define GDB_FR_FPR4            ((GDB_FR_FPR3) + 4)             /* 42 */
+#define GDB_FR_FPR5            ((GDB_FR_FPR4) + 4)             /* 43 */
+#define GDB_FR_FPR6            ((GDB_FR_FPR5) + 4)             /* 44 */
+#define GDB_FR_FPR7            ((GDB_FR_FPR6) + 4)             /* 45 */
+#define GDB_FR_FPR8            ((GDB_FR_FPR7) + 4)             /* 46 */
+#define GDB_FR_FPR9            ((GDB_FR_FPR8) + 4)             /* 47 */
+#define GDB_FR_FPR10           ((GDB_FR_FPR9) + 4)             /* 48 */
+#define GDB_FR_FPR11           ((GDB_FR_FPR10) + 4)            /* 49 */
+#define GDB_FR_FPR12           ((GDB_FR_FPR11) + 4)            /* 50 */
+#define GDB_FR_FPR13           ((GDB_FR_FPR12) + 4)            /* 51 */
+#define GDB_FR_FPR14           ((GDB_FR_FPR13) + 4)            /* 52 */
+#define GDB_FR_FPR15           ((GDB_FR_FPR14) + 4)            /* 53 */
+#define GDB_FR_FPR16           ((GDB_FR_FPR15) + 4)            /* 54 */
+#define GDB_FR_FPR17           ((GDB_FR_FPR16) + 4)            /* 55 */
+#define GDB_FR_FPR18           ((GDB_FR_FPR17) + 4)            /* 56 */
+#define GDB_FR_FPR19           ((GDB_FR_FPR18) + 4)            /* 57 */
+#define GDB_FR_FPR20           ((GDB_FR_FPR19) + 4)            /* 58 */
+#define GDB_FR_FPR21           ((GDB_FR_FPR20) + 4)            /* 59 */
+#define GDB_FR_FPR22           ((GDB_FR_FPR21) + 4)            /* 60 */
+#define GDB_FR_FPR23           ((GDB_FR_FPR22) + 4)            /* 61 */
+#define GDB_FR_FPR24           ((GDB_FR_FPR23) + 4)            /* 62 */
+#define GDB_FR_FPR25           ((GDB_FR_FPR24) + 4)            /* 63 */
+#define GDB_FR_FPR26           ((GDB_FR_FPR25) + 4)            /* 64 */
+#define GDB_FR_FPR27           ((GDB_FR_FPR26) + 4)            /* 65 */
+#define GDB_FR_FPR28           ((GDB_FR_FPR27) + 4)            /* 66 */
+#define GDB_FR_FPR29           ((GDB_FR_FPR28) + 4)            /* 67 */
+#define GDB_FR_FPR30           ((GDB_FR_FPR29) + 4)            /* 68 */
+#define GDB_FR_FPR31           ((GDB_FR_FPR30) + 4)            /* 69 */
+
+#define GDB_FR_FSR             ((GDB_FR_FPR31) + 4)            /* 70 */
+#define GDB_FR_FIR             ((GDB_FR_FSR) + 4)              /* 71 */
+#define GDB_FR_FRP             ((GDB_FR_FIR) + 4)              /* 72 */
+
+#define GDB_FR_DUMMY           ((GDB_FR_FRP) + 4)              /* 73, unused ??? */
+
+/*
+ * Again, CP0 registers
+ */
+#define GDB_FR_CP0_INDEX       ((GDB_FR_DUMMY) + 4)            /* 74 */
+#define GDB_FR_CP0_RANDOM      ((GDB_FR_CP0_INDEX) + 4)        /* 75 */
+#define GDB_FR_CP0_ENTRYLO0    ((GDB_FR_CP0_RANDOM) + 4)       /* 76 */
+#define GDB_FR_CP0_ENTRYLO1    ((GDB_FR_CP0_ENTRYLO0) + 4)     /* 77 */
+#define GDB_FR_CP0_REG4                ((GDB_FR_CP0_ENTRYLO1) + 4)     /* 78 */
+#define GDB_FR_CP0_PAGEMASK    ((GDB_FR_CP0_REG4) + 4)         /* 79 */
+#define GDB_FR_CP0_WIRED       ((GDB_FR_CP0_PAGEMASK) + 4)     /* 80 */
+#define GDB_FR_CP0_REG7                ((GDB_FR_CP0_WIRED) + 4)        /* 81 */
+#define GDB_FR_CP0_REG8                ((GDB_FR_CP0_REG7) + 4)         /* 82 */
+#define GDB_FR_CP0_REG9                ((GDB_FR_CP0_REG8) + 4)         /* 83 */
+#define GDB_FR_CP0_ENTRYHI     ((GDB_FR_CP0_REG9) + 4)         /* 84 */
+#define GDB_FR_CP0_REG11       ((GDB_FR_CP0_ENTRYHI) + 4)      /* 85 */
+#define GDB_FR_CP0_REG12       ((GDB_FR_CP0_REG11) + 4)        /* 86 */
+#define GDB_FR_CP0_REG13       ((GDB_FR_CP0_REG12) + 4)        /* 87 */
+#define GDB_FR_CP0_REG14       ((GDB_FR_CP0_REG13) + 4)        /* 88 */
+#define GDB_FR_CP0_PRID                ((GDB_FR_CP0_REG14) + 4)        /* 89 */
+
+#define GDB_FR_SIZE            ((((GDB_FR_CP0_PRID) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1))
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+/*
+ * This is the same as above, but for the high-level
+ * part of the GDB stub.
+ */
+
+struct gdb_regs {
+       /*
+        * Pad bytes for argument save space on the stack
+        * 20/40 Bytes for 32/64 bit code
+        */
+       unsigned long pad0[5];
+
+       /*
+        * saved main processor registers
+        */
+       long     reg0,  reg1,  reg2,  reg3,  reg4,  reg5,  reg6,  reg7;
+       long     reg8,  reg9, reg10, reg11, reg12, reg13, reg14, reg15;
+       long    reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+       long    reg24, reg25, reg26, reg27, reg28, reg29, reg30, reg31;
+
+       /*
+        * Saved special registers
+        */
+       long    cp0_status;
+       long    lo;
+       long    hi;
+       long    cp0_badvaddr;
+       long    cp0_cause;
+       long    cp0_epc;
+
+       /*
+        * Saved floating point registers
+        */
+       long    fpr0,  fpr1,  fpr2,  fpr3,  fpr4,  fpr5,  fpr6,  fpr7;
+       long    fpr8,  fpr9,  fpr10, fpr11, fpr12, fpr13, fpr14, fpr15;
+       long    fpr16, fpr17, fpr18, fpr19, fpr20, fpr21, fpr22, fpr23;
+       long    fpr24, fpr25, fpr26, fpr27, fpr28, fpr29, fpr30, fpr31;
+
+       long    cp1_fsr;
+       long    cp1_fir;
+
+       /*
+        * Frame pointer
+        */
+       long    frame_ptr;
+       long    dummy;          /* unused */
+       
+       /*
+        * saved cp0 registers
+        */
+       long    cp0_index;
+       long    cp0_random;
+       long    cp0_entrylo0;
+       long    cp0_entrylo1;
+       long    cp0_reg4;
+       long    cp0_pagemask;
+       long    cp0_wired;
+       long    cp0_reg7;
+       long    cp0_reg8;
+       long    cp0_reg9;
+       long    cp0_entryhi;
+       long    cp0_reg11;
+       long    cp0_reg12;
+       long    cp0_reg13;
+       long    cp0_reg14;
+       long    cp0_prid;
+};
+
+/*
+ * Prototypes
+ */
+
+void set_debug_traps(void);
+
+#endif /* __LANGUAGE_ASSEMBLY */
+#endif /* __ASM_MIPS_GDB_STUB_H */
index 40ac19e41ef9c43c809b746a7704d40a2f5513c7..d1c5a340ab2a0f40a8d1006426f5bd732d2fe2b4 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ASM_MIPS_IO_H
 #define __ASM_MIPS_IO_H
 
-#include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
+#include <asm/segment.h>
 
 /*
  * This file contains the definitions for the MIPS counterpart of the
 #define SLOW_DOWN_IO __SLOW_DOWN_IO
 #endif
 
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are trivial on the 1:1 Linux/MIPS mapping
+ */
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+       return (unsigned long) address - KSEG0;
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+       return (void *) address + KSEG0;
+}
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ * FIXME: This assumption is wrong for the Deskstation Tyne
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+
+#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
+
+/*
+ * Again, MIPS does not require mem IO specific function.
+ */
+
+#define eth_io_copy_and_sum(a,b,c,d)   eth_copy_and_sum((a),(void *)(b),(c),(d))
+
 /*
  * Talk about misusing macros..
  */
@@ -58,23 +103,26 @@ __asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
 
 #define __OUT(m,s) \
 __OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); } \
-__OUT1(s##c) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); } \
+__OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (PORT_BASE)); } \
 __OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); \
        SLOW_DOWN_IO; } \
-__OUT1(s##c_p) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); \
+__OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (PORT_BASE)); \
        SLOW_DOWN_IO; }
 
-#define __IN1(s) \
-extern inline unsigned int __in##s(unsigned int port) { unsigned int _v;
+#define __IN1(t,s) \
+extern __inline__ t __in##s(unsigned int port) { t _v;
 
+/*
+ * Useless nops will be removed by the assembler
+ */
 #define __IN2(m) \
-__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\t"
+__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\tnop"
 
-#define __IN(m,s) \
-__IN1(s) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
-__IN1(s##c) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); return _v; } \
-__IN1(s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
-__IN1(s##c_p) __IN2(m) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
+#define __IN(t,m,s) \
+__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
+__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (PORT_BASE)); return _v; } \
+__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
+__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
 
 #define __INS1(s) \
 extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
@@ -84,10 +132,10 @@ __asm__ __volatile__ ( \
        ".set\tnoreorder\n\t" \
        ".set\tnoat\n" \
        "1:\tl" #m "u\t$1,%4(%5)\n\t" \
-       "subu\t%1,%1,1\n\t" \
+       "subu\t%1,1\n\t" \
        "s" #m "\t$1,(%0)\n\t" \
        "bne\t$0,%1,1b\n\t" \
-       "addiu\t%0,%0,%6\n\t" \
+       "addiu\t%0,%6\n\t" \
        ".set\tat\n\t" \
        ".set\treorder"
 
@@ -98,7 +146,7 @@ __INS1(s) __INS2(m) \
        : "$1");} \
 __INS1(s##c) __INS2(m) \
        : "=r" (addr), "=r" (count) \
-       : "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
+       : "0" (addr), "1" (count), "ir" (port), "r" (PORT_BASE), "I" (i) \
        : "$1");}
 
 #define __OUTS1(s) \
@@ -123,12 +171,12 @@ __OUTS1(s) __OUTS2(m) \
        : "$1");} \
 __OUTS1(s##c) __OUTS2(m) \
        : "=r" (addr), "=r" (count) \
-       : "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
+       : "0" (addr), "1" (count), "ir" (port), "r" (PORT_BASE), "I" (i) \
        : "$1");}
 
-__IN(b,b)
-__IN(h,w)
-__IN(w,l)
+__IN(unsigned char,b,b)
+__IN(unsigned short,h,w)
+__IN(unsigned int,w,l)
 
 __OUT(b,b)
 __OUT(h,w)
diff --git a/include/asm-mips/ioctl.h b/include/asm-mips/ioctl.h
new file mode 100644 (file)
index 0000000..af6fd89
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef __ASM_MIPS_IOCTL_H
+#define __ASM_MIPS_IOCTL_H
+
+/*
+ * The original linux ioctl numbering scheme was just a general
+ * "anything goes" setup, where more or less random numbers were
+ * assigned.  Sorry, I was clueless when I started out on this.
+ *
+ * On the alpha, we'll try to clean it up a bit, using a more sane
+ * ioctl numbering, and also trying to be compatible with OSF/1 in
+ * the process. I'd like to clean it up for the i386 as well, but
+ * it's so painful recognizing both the new and the old numbers..
+ *
+ * The same applies for for the MIPS ABI; in fact even the macros
+ * from Linux/Alpha fit almost perfectly.
+ */
+
+#define _IOC_NRBITS    8
+#define _IOC_TYPEBITS  8
+#define _IOC_SIZEBITS  13
+#define _IOC_DIRBITS   3
+
+#define _IOC_NRMASK    ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK  ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK   ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT   0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * We to additionally limit parameters to a maximum 255 bytes.
+ */
+#define _IOC_SLMASK    0xff
+
+/*
+ * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
+ * And this turns out useful to catch old ioctl numbers in header
+ * files for us.
+ */
+#define _IOC_NONE      1U
+#define _IOC_READ      2U
+#define _IOC_WRITE     4U
+
+/*
+ * The following are included for compatibility
+ */
+#define _IOC_VOID      0x20000000
+#define _IOC_OUT       0x40000000
+#define _IOC_IN                0x80000000
+#define _IOC_INOUT     (IOC_IN|IOC_OUT)
+
+#define _IOC(dir,type,nr,size) \
+       (((dir)  << _IOC_DIRSHIFT) | \
+        ((type) << _IOC_TYPESHIFT) | \
+        ((nr)   << _IOC_NRSHIFT) | \
+        (((size) & _IOC_SLMASK) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)           _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)     _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)     _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode them.. */
+#define _IOC_DIR(nr)           (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)          (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)            (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)          (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN         (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT                (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT      ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK   (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT  (_IOC_SIZESHIFT)
+
+#endif /* __ASM_MIPS_IOCTL_H */
diff --git a/include/asm-mips/ioctls.h b/include/asm-mips/ioctls.h
new file mode 100644 (file)
index 0000000..aaf7a03
--- /dev/null
@@ -0,0 +1,299 @@
+#ifndef __ASM_MIPS_IOCTLS_H
+#define __ASM_MIPS_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define TCGETA         0x5401
+#define TCSETA         0x5402
+#define TCSETAW                0x5403
+#define TCSETAF                0x5404
+
+#define TCSBRK         0x5405
+#define TCXONC         0x5406
+#define TCFLSH         0x5407
+
+#define TCGETS         0x540d
+#define TCSETS         0x540e
+#define TCSETSW                0x540f
+#define TCSETSF                0x5410
+
+#define TIOCEXCL       0x740d          /* set exclusive use of tty */
+#define TIOCNXCL       0x740e          /* reset exclusive use of tty */
+#define TIOCOUTQ       0x7472          /* output queue size */
+#define TIOCSTI                0x5472          /* simulate terminal input */
+#define TIOCMGET       0x741d          /* get all modem bits */
+#define TIOCMBIS       0x741b          /* bis modem bits */
+#define TIOCMBIC       0x741c          /* bic modem bits */
+#define TIOCMSET       0x741a          /* set all modem bits */
+#define TIOCPKT                0x5470          /* pty: set/clear packet mode */
+#define                TIOCPKT_DATA            0x00    /* data packet */
+#define                TIOCPKT_FLUSHREAD       0x01    /* flush packet */
+#define                TIOCPKT_FLUSHWRITE      0x02    /* flush packet */
+#define                TIOCPKT_STOP            0x04    /* stop output */
+#define                TIOCPKT_START           0x08    /* start output */
+#define                TIOCPKT_NOSTOP          0x10    /* no more ^S, ^Q */
+#define                TIOCPKT_DOSTOP          0x20    /* now do ^S ^Q */
+#if 0
+#define                TIOCPKT_IOCTL           0x40    /* state change of pty driver */
+#endif
+#define TIOCSWINSZ     _IOW('t', 103, struct winsize)  /* set window size */
+#define TIOCGWINSZ     _IOR('t', 104, struct winsize)  /* get window size */
+#define TIOCNOTTY      0x5471          /* void tty association */
+#define TIOCSETD       0x7401
+#define TIOCGETD       0x7400
+
+#define FIOCLEX                0x6601
+#define FIONCLEX       0x6602          /* these numbers need to be adjusted. */
+#define FIOASYNC       0x667d
+#define FIONBIO                0x667e
+
+                                               /* 116-117 compat */
+#define TIOCSPGRP      _IOW('t', 118, int)     /* set pgrp of tty */
+#define TIOCGPGRP      _IOR('t', 119, int)     /* get pgrp of tty */
+#define TIOCCONS       _IOW('t', 120, int)     /* become virtual console */
+
+#define FIONREAD       0x467f
+#define TIOCINQ                FIONREAD
+
+#if 0
+#define        TIOCSETA        _IOW('t', 20, struct termios) /* set termios struct */
+#define        TIOCSETAW       _IOW('t', 21, struct termios) /* drain output, set */
+#define        TIOCSETAF       _IOW('t', 22, struct termios) /* drn out, fls in, set */
+#define        TIOCGETD        _IOR('t', 26, int)      /* get line discipline */
+#define        TIOCSETD        _IOW('t', 27, int)      /* set line discipline */
+                                               /* 127-124 compat */
+#endif
+
+/* I hope the range from 0x5480 on is free ... */
+#define TIOCSCTTY      0x5480          /* become controlling tty */
+#define TIOCGSOFTCAR   0x5481
+#define TIOCSSOFTCAR   0x5482
+#define TIOCLINUX      0x5483
+#define TIOCGSERIAL    0x5484
+#define TIOCSSERIAL    0x5485
+
+#define TCSBRKP                0x5486  /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT 0x5487  /* For debugging only */
+
+#define TIOCSERCONFIG  0x5488
+#define TIOCSERGWILD   0x5489
+#define TIOCSERSWILD   0x548a
+#define TIOCGLCKTRMIOS 0x548b
+#define TIOCSLCKTRMIOS 0x548c
+#define TIOCSERGSTRUCT 0x548d /* For debugging only */
+#define TIOCSERGETLSR   0x548e /* Get line status register */
+#define TIOCSERGETMULTI 0x548f /* Get multiport config  */
+#define TIOCSERSETMULTI 0x5490 /* Set multiport config */
+
+/* ----------------------------------------------------------------------- */
+
+/* c_cc characters */
+#define VINTR           0              /* Interrupt character [ISIG].  */
+#define VQUIT           1              /* Quit character [ISIG].  */
+#define VERASE          2              /* Erase character [ICANON].  */
+#define VKILL           3              /* Kill-line character [ICANON].  */
+#define VEOF            4              /* End-of-file character [ICANON].  */
+#define VMIN           VEOF            /* Minimum number of bytes read at once [!ICANON].  */
+#define VEOL            5              /* End-of-line character [ICANON].  */
+#define VTIME          VEOL            /* Time-out value (tenths of a second) [!ICANON].  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VEOL2           6              /* Second EOL character [ICANON].  */
+/* The next two are guesses ... */
+#define VSWTC           7              /* ??? */
+#endif
+#define VSWTCH         VSWTC
+#define VSTART          8              /* Start (X-ON) character [IXON, IXOFF].  */
+#define VSTOP           9              /* Stop (X-OFF) character [IXON, IXOFF].  */
+#define VSUSP          10              /* Suspend character [ISIG].  */
+#if 0
+/*
+ * VDSUSP is not supported
+ */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VDSUSP         11              /* Delayed suspend character [ISIG].  */
+#endif
+#endif
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VREPRINT       12              /* Reprint-line character [ICANON].  */
+#endif
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VDISCARD       13              /* Discard character [IEXTEN].  */
+#define VWERASE                14              /* Word-erase character [ICANON].  */
+#define VLNEXT         15              /* Literal-next character [IEXTEN].  */
+#endif
+/*
+ * 17 - 19 are reserved
+ */
+
+#ifdef __KERNEL__
+/*
+ *     intr=^C         quit=^|         erase=del       kill=^U
+ *     eof=^D          eol=time=\0     eol2=\0         swtc=\0
+ *     start=^Q        stop=^S         susp=^Z         vdsusp=
+ *     reprint=^R      discard=^U      werase=^W       lnext=^V
+ */
+#define INIT_C_CC "\003\034\177\025\004\0\0\0\021\023\032\0\022\017\027\026"
+#endif
+
+/* c_iflag bits */
+#define IGNBRK 0000001         /* Ignore break condition.  */
+#define BRKINT 0000002         /* Signal interrupt on break.  */
+#define IGNPAR 0000004         /* Ignore characters with parity errors.  */
+#define PARMRK 0000010         /* Mark parity and framing errors.  */
+#define INPCK  0000020         /* Enable input parity check.  */
+#define ISTRIP 0000040         /* Strip 8th bit off characters.  */
+#define INLCR  0000100         /* Map NL to CR on input.  */
+#define IGNCR  0000200         /* Ignore CR.  */
+#define ICRNL  0000400         /* Map CR to NL on input.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IUCLC  0001000         /* Map upper case to lower case on input.  */
+#endif
+#define IXON   0002000         /* Enable start/stop output control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IXANY  0004000         /* Any character will restart after stop.  */
+#endif
+#define IXOFF  0010000         /* Enable start/stop input control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IMAXBEL        0020000         /* Ring bell when input queue is full.  */
+#endif
+
+/* c_oflag bits */
+#define OPOST  0000001         /* Perform output processing.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define OLCUC  0000002         /* Map lower case to upper case on output.  */
+#define ONLCR  0000004         /* Map NL to CR-NL on output.  */
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+/*
+#define PAGEOUT ???
+#define WRAP    ???
+ */
+#endif
+
+/* c_cflag bit meaning */
+#define CBAUD  0010017
+#define  B0    0000000         /* hang up */
+#define  B50   0000001
+#define  B75   0000002
+#define  B110  0000003
+#define  B134  0000004
+#define  B150  0000005
+#define  B200  0000006
+#define  B300  0000007
+#define  B600  0000010
+#define  B1200 0000011
+#define  B1800 0000012
+#define  B2400 0000013
+#define  B4800 0000014
+#define  B9600 0000015
+#define  B19200        0000016
+#define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE  0000060         /* Number of bits per byte (mask).  */
+#define   CS5  0000000         /* 5 bits per byte.  */
+#define   CS6  0000020         /* 6 bits per byte.  */
+#define   CS7  0000040         /* 7 bits per byte.  */
+#define   CS8  0000060         /* 8 bits per byte.  */
+#define CSTOPB 0000100         /* Two stop bits instead of one.  */
+#define CREAD  0000200         /* Enable receiver.  */
+#define PARENB 0000400         /* Parity enable.  */
+#define PARODD 0001000         /* Odd parity instead of even.  */
+#define HUPCL  0002000         /* Hang up on last close.  */
+#define CLOCAL 0004000         /* Ignore modem status lines.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define CIBAUD   002003600000  /* input baud rate (not used) */
+#define CRTSCTS          020000000000          /* flow control */
+#endif
+
+/* c_lflag bits */
+#define ISIG   0000001         /* Enable signals.  */
+#define ICANON 0000002         /* Do erase and kill processing.  */
+#define XCASE  0000004
+#define ECHO   0000010         /* Enable echo.  */
+#define ECHOE  0000020         /* Visual erase for ERASE.  */
+#define ECHOK  0000040         /* Echo NL after KILL.  */
+#define ECHONL 0000100         /* Echo NL even if ECHO is off.  */
+#define NOFLSH 0000200         /* Disable flush after interrupt.  */
+#define IEXTEN 0000400         /* Enable DISCARD and LNEXT.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define ECHOCTL        0001000         /* Echo control characters as ^X.  */
+#define ECHOPRT        0002000         /* Hardcopy visual erase.  */
+#define ECHOKE 0004000         /* Visual erase for KILL.  */
+#endif
+#define FLUSHO 0020000
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define PENDIN 0040000         /* Retype pending input (state).  */
+#endif
+#define TOSTOP 0100000         /* Send SIGTTOU for background output.  */
+#define ITOSTOP        TOSTOP
+
+/* modem lines */
+#define TIOCM_LE       0x001           /* line enable */
+#define TIOCM_DTR      0x002           /* data terminal ready */
+#define TIOCM_RTS      0x004           /* request to send */
+#define TIOCM_ST       0x010           /* secondary transmit */
+#define TIOCM_SR       0x020           /* secondary receive */
+#define TIOCM_CTS      0x040           /* clear to send */
+#define TIOCM_CAR      0x100           /* carrier detect */
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RNG      0x200           /* ring */
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_DSR      0x400           /* data set ready */
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0       /* Suspend output.  */
+#define        TCOON           1       /* Restart suspended output.  */
+#define        TCIOFF          2       /* Send a STOP character.  */
+#define        TCION           3       /* Send a START character.  */
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0       /* Discard data received but not yet read.  */
+#define        TCOFLUSH        1       /* Discard data written but not yet sent.  */
+#define        TCIOFLUSH       2       /* Discard all pending data.  */
+
+/* tcsetattr uses these */
+#define        TCSANOW         TCSETS  /* Change immediately.  */
+#define        TCSADRAIN       TCSETSW /* Change when pending output is written.  */
+#define        TCSAFLUSH       TCSETSF /* Flush pending input before changing.  */
+
+/* line disciplines */
+#define N_TTY          0
+#define N_SLIP         1
+#define N_MOUSE                2
+#define N_PPP          3
+
+#endif /* __ASM_MIPS_IOCTLS_H */
index 4c5191fef9d4b99e113eafad7904ab3834c388ed..bce4feabb4470793bf0acb7d8bcd46ec205722c8 100644 (file)
 #ifndef __ASM_MIPS_IRQ_H
 #define __ASM_MIPS_IRQ_H
 
+/*
+ * Actually this is a lie but we hide the local device's interrupts ...
+ */
+#define NR_IRQS 16
+
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
 
diff --git a/include/asm-mips/jazz.h b/include/asm-mips/jazz.h
new file mode 100644 (file)
index 0000000..a9934a4
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Hardware info about Mips JAZZ and similar systems
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Andreas Busse and Ralf Baechle
+ *
+ * This file is a mess. It really needs some reorganisation!
+ */
+
+#ifndef __ASM_MIPS_JAZZ_H 
+#define __ASM_MIPS_JAZZ_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb. The Mips
+ * Magnum R3000 and R4000 machines are similar in many aspects,
+ * but many hardware register are accessible at 0xb9000000 in
+ * instead of 0xe0000000.
+ */
+
+#define JAZZ_LOCAL_IO_SPACE     0xe0000000
+
+/*
+ * Revision numbers in PICA_ASIC_REVISION
+ *
+ * 0xf0000000 - Rev1
+ * 0xf0000001 - Rev2
+ * 0xf0000002 - Rev3
+ */
+#define PICA_ASIC_REVISION      0xe0000008
+
+/*
+ * The segments of the seven segment LED are mapped
+ * to the control bits as follows:
+ *
+ *         (7)
+ *      ---------
+ *      |       |
+ *  (2) |       | (6)
+ *      |  (1)  |
+ *      ---------
+ *      |       |
+ *  (3) |       | (5)
+ *      |  (4)  |
+ *      --------- . (0)
+ */
+#define PICA_LED                0xe000f000
+
+/*
+ * Some characters for the LED control registers
+ * The original Mips machines seem to have a LED display
+ * with integrated decoder while the Acer machines can
+ * control each of the seven segments and the dot independend.
+ * It's only a toy, anyway...
+ */
+#define LED_DOT                 0x01
+#define LED_SPACE               0x00
+#define LED_0                   0xfc
+#define LED_1                   0x60
+#define LED_2                   0xda
+#define LED_3                   0xf2
+#define LED_4                   0x66
+#define LED_5                   0xb6
+#define LED_6                   0xbe
+#define LED_7                   0xe0
+#define LED_8                   0xfe
+#define LED_9                   0xf6
+#define LED_A                   0xee
+#define LED_b                   0x3e
+#define LED_C                   0x9c
+#define LED_d                   0x7a
+#define LED_E                   0x9e
+#define LED_F                   0x8e
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pica_set_led(unsigned int bits)
+{
+       volatile unsigned int *led_register = (unsigned int *) PICA_LED;
+
+       *led_register = bits;
+}
+
+#endif
+
+/*
+ * i8042 keyboard controller for JAZZ and PICA chipsets.
+ * This address is just a guess and seems to differ from
+ * other mips machines such as RC3xxx...
+ */
+#define JAZZ_KEYBOARD_ADDRESS   0xe0005000
+#define JAZZ_KEYBOARD_DATA      0xe0005000
+#define JAZZ_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+       unsigned char data;
+       unsigned char command;
+} jazz_keyboard_hardware;
+
+typedef struct {
+       unsigned char pad0[3];
+       unsigned char data;
+       unsigned char pad1[3];
+       unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now. Needs to be changed for RC3xxx support. See below.
+ */
+#define keyboard_hardware       jazz_keyboard_hardware
+
+#endif
+
+/*
+ * i8042 keyboard controller for most other Mips machines.
+ */
+#define MIPS_KEYBOARD_ADDRESS   0xb9005000
+#define MIPS_KEYBOARD_DATA      0xb9005003
+#define MIPS_KEYBOARD_COMMAND   0xb9005007
+
+/*
+ * Serial and parallel ports (WD 16C552) on the Mips JAZZ
+ */
+#define JAZZ_SERIAL1_BASE       (unsigned int)0xe0006000
+#define JAZZ_SERIAL2_BASE       (unsigned int)0xe0007000
+#define JAZZ_PARALLEL_BASE      (unsigned int)0xe0008000
+
+/*
+ * Dummy Device Address. Used in jazzdma.c
+ */
+#define JAZZ_DUMMY_DEVICE       0xe000d000
+     
+/*
+ * JAZZ timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define JAZZ_TIMER_INTERVAL     0xe0000228
+#define JAZZ_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+       unsigned int bank2 : 3;
+       unsigned int bank1 : 3;
+       unsigned int mem_bus_width : 1;
+       unsigned int reserved2 : 1;
+       unsigned int page_mode : 1;
+       unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+       unsigned int reserved1 : 23;
+       unsigned int page_mode : 1;
+       unsigned int reserved2 : 1;
+       unsigned int mem_bus_width : 1;
+       unsigned int bank1 : 3;
+       unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PICA_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * JAZZ interrupt control registers
+ */
+#define JAZZ_IO_IRQ_SOURCE      0xe0100000
+#define JAZZ_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * JAZZ interrupt enable bits
+ */
+#define JAZZ_IE_PARALLEL            (1 << 0)
+#define JAZZ_IE_FLOPPY              (1 << 1)
+#define JAZZ_IE_SOUND               (1 << 2)
+#define JAZZ_IE_VIDEO               (1 << 3)
+#define JAZZ_IE_ETHERNET            (1 << 4)
+#define JAZZ_IE_SCSI                (1 << 5)
+#define JAZZ_IE_KEYBOARD            (1 << 6)
+#define JAZZ_IE_MOUSE               (1 << 7)
+#define JAZZ_IE_SERIAL1             (1 << 8)
+#define JAZZ_IE_SERIAL2             (1 << 9)
+
+/*
+ * JAZZ Interrupt Level definitions
+ */
+#define JAZZ_TIMER_IRQ          0
+#define JAZZ_KEYBOARD_IRQ       1
+#define JAZZ_ETHERNET_IRQ       2 /* 15 */
+#define JAZZ_SERIAL1_IRQ        3
+#define JAZZ_SERIAL2_IRQ        4
+#define JAZZ_PARALLEL_IRQ       5
+#define JAZZ_FLOPPY_IRQ         6 /* needs to be consistent with floppy driver! */
+
+
+/*
+ * JAZZ DMA Channels
+ * Note: Channels 4...7 are not used with respect to the Acer PICA-61
+ * chipset which does not provide these DMA channels.
+ */
+#define JAZZ_SCSI_DMA           0              /* SCSI */
+#define JAZZ_FLOPPY_DMA         1              /* FLOPPY */
+#define JAZZ_AUDIOL_DMA         2              /* AUDIO L */
+#define JAZZ_AUDIOR_DMA         3              /* AUDIO R */
+
+/*
+ * JAZZ R4030 MCT_ADR chip (DMA controller)
+ * Note: Virtual Addresses !
+ */
+#define JAZZ_R4030_CONFIG      0xE0000000      /* R4030 config register */
+#define JAZZ_R4030_REVISION     0xE0000008     /* same as PICA_ASIC_REVISION */
+#define JAZZ_R4030_INV_ADDR    0xE0000010      /* Invalid Address register */
+
+#define JAZZ_R4030_TRSTBL_BASE  0xE0000018     /* Translation Table Base */
+#define JAZZ_R4030_TRSTBL_LIM   0xE0000020     /* Translation Table Limit */
+#define JAZZ_R4030_TRSTBL_INV   0xE0000028     /* Translation Table Invalidate */
+
+#define JAZZ_R4030_CACHE_MTNC   0xE0000030     /* Cache Maintenance */
+#define JAZZ_R4030_R_FAIL_ADDR  0xE0000038     /* Remote Failed Address */
+#define JAZZ_R4030_M_FAIL_ADDR  0xE0000040     /* Memory Failed Adresss */
+
+#define JAZZ_R4030_CACHE_PTAG   0xE0000048     /* I/O Cache Physical Tag */
+#define JAZZ_R4030_CACHE_LTAG   0xE0000050     /* I/O Cache Logical Tag */
+#define JAZZ_R4030_CACHE_BMASK  0xE0000058     /* I/O Cache Byte Mask */
+#define JAZZ_R4030_CACHE_BWIN   0xE0000060     /* I/O Cache Buffer Window */
+
+/*
+ * Remote Speed Registers. 
+ *
+ *  0: free,      1: Ethernet,  2: SCSI,      3: Floppy,
+ *  4: RTC,       5: Kb./Mouse  6: serial 1,  7: serial 2,
+ *  8: parallel,  9: NVRAM,    10: CPU,      11: PROM,
+ * 12: reserved, 13: free,     14: 7seg LED, 15: ???
+ */
+#define JAZZ_R4030_REM_SPEED   0xE0000070      /* 16 Remote Speed Registers */
+                                               /* 0xE0000070,78,80... 0xE00000E8 */
+#define JAZZ_R4030_IRQ_ENABLE   0xE00000E8     /* Internal Interrupt Enable */
+
+#define JAZZ_R4030_IRQ_SOURCE   0xE0000200     /* Interrupt Source Reg */
+#define JAZZ_R4030_I386_ERROR   0xE0000208     /* i386/EISA Bus Error */
+
+
+/*
+ * Access the R4030 DMA and I/O Controller
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern inline unsigned short r4030_read_reg16(unsigned addr) {
+       unsigned short ret = *((volatile unsigned short *)addr);
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               ".set\treorder");
+       return ret;
+}
+
+extern inline unsigned int r4030_read_reg32(unsigned addr) {
+       unsigned int ret = *((volatile unsigned int *)addr);
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               ".set\treorder");
+       return ret;
+}
+
+extern inline void r4030_write_reg16(unsigned addr, unsigned val) {
+       *((volatile unsigned short *)addr) = val;
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               ".set\treorder");
+}
+
+extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) {
+       *((volatile unsigned int *)addr) = val;
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               ".set\treorder");
+}
+
+#endif /* !LANGUAGE_ASSEMBLY__ */
+
+#define JAZZ_FDC_BASE 0xe0003000
+
+#define JAZZ_RTC_BASE 0xe0004000
+
+#endif /* __ASM_MIPS_JAZZ_H */
diff --git a/include/asm-mips/jazzdma.h b/include/asm-mips/jazzdma.h
new file mode 100644 (file)
index 0000000..582acdc
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
+ */
+
+#ifndef __ASM_JAZZDMA_H
+#define __ASM_JAZZDMA_H
+
+/*
+ * Prototypes and macros
+ */
+
+unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end);
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
+int vdma_free(unsigned long laddr);
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size);
+unsigned long vdma_phys2log(unsigned long paddr);
+unsigned long vdma_log2phys(unsigned long laddr);
+void vdma_stats(void);         /* for debugging only */
+
+void vdma_enable(int channel);
+void vdma_disable(int channel);
+void vdma_set_mode(int channel, int mode);
+void vdma_set_addr(int channel, long addr);
+void vdma_set_count(int channel, int count);
+int vdma_get_residue(int channel);
+
+/*
+ * some definitions used by the driver functions
+ */
+#define VDMA_PAGESIZE          4096
+#define VDMA_PGTBL_ENTRIES     4096
+#define VDMA_PGTBL_SIZE                (sizeof(VDMA_PGTBL_ENTRY) * VDMA_PGTBL_ENTRIES)
+#define VDMA_PAGE_EMPTY                0
+
+/*
+ * Macros to get page no. and offset of a given address
+ * Note that VDMA_PAGE() works for physical addresses only
+ */
+#define VDMA_PAGE(a)            ((unsigned int)(a) >> 12)
+#define VDMA_OFFSET(a)          ((unsigned int)(a) & (VDMA_PAGESIZE-1))
+
+/*
+ * error code returned by vdma_alloc()
+ * (See also arch/mips/kernel/jazzdma.c)
+ */
+#define VDMA_ERROR              0xffffffff
+
+/*
+ * VDMA pagetable entry description
+ */
+typedef volatile struct VDMA_PGTBL_ENTRY
+{
+       unsigned int frame;             /* physical frame no. */
+       unsigned int owner;             /* owner of this entry (0=free) */
+} VDMA_PGTBL_ENTRY;
+
+
+/*
+ * DMA channel control registers
+ * in the R4030 MCT_ADR chip
+ */
+#define JAZZ_R4030_CHNL_MODE   0xE0000100      /* 8 DMA Channel Mode Registers, */
+                                               /* 0xE0000100,120,140... */
+#define JAZZ_R4030_CHNL_ENABLE  0xE0000108     /* 8 DMA Channel Enable Regs, */
+                                               /* 0xE0000108,128,148... */
+#define JAZZ_R4030_CHNL_COUNT   0xE0000110     /* 8 DMA Channel Byte Cnt Regs, */
+                                               /* 0xE0000110,130,150... */
+#define JAZZ_R4030_CHNL_ADDR   0xE0000118      /* 8 DMA Channel Address Regs, */
+                                               /* 0xE0000118,138,158... */
+
+/* channel enable register bits */
+
+#define R4030_CHNL_ENABLE        (1<<0)
+#define R4030_CHNL_WRITE         (1<<1)
+#define R4030_TC_INTR            (1<<8)
+#define R4030_MEM_INTR           (1<<9)
+#define R4030_ADDR_INTR          (1<<10)
+
+/* channel mode register bits */
+
+#define R4030_MODE_ATIME_40      (0) /* device access time on remote bus */
+#define R4030_MODE_ATIME_80      (1)
+#define R4030_MODE_ATIME_120     (2)
+#define R4030_MODE_ATIME_160     (3)
+#define R4030_MODE_ATIME_200     (4)
+#define R4030_MODE_ATIME_240     (5)
+#define R4030_MODE_ATIME_280     (6)
+#define R4030_MODE_ATIME_320     (7)
+#define R4030_MODE_WIDTH_8       (1<<3)        /* device data bus width */
+#define R4030_MODE_WIDTH_16      (2<<3)
+#define R4030_MODE_WIDTH_32      (3<<3)
+#define R4030_MODE_INTR_EN       (1<<5)
+#define R4030_MODE_BURST         (1<<6)        /* Rev. 2 only */
+#define R4030_MODE_FAST_ACK      (1<<7)        /* Rev. 2 only */
+
+#endif /* __ASM_JAZZDMA_H */
diff --git a/include/asm-mips/mc146818rtc.h b/include/asm-mips/mc146818rtc.h
new file mode 100644 (file)
index 0000000..2b39a32
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Machine dependend access functions for RTC registers.
+ */
+#ifndef __ASM_MIPS_MC146818RTC_H
+#define __ASM_MIPS_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/vector.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x)    (0x70 + (x))
+#define RTC_ALWAYS_BCD 1
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+feature->rtc_read_data(); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+feature->rtc_write_data(val); \
+})
+
+#endif /* __ASM_MIPS_MC146818RTC_H */
index f4acad0a17efd7a4c50959c8bc042038725ec5e7..0585d93943068223c7347898633bf346d6c137d3 100644 (file)
@@ -1,29 +1,26 @@
 /*
- * linux/include/asm-mips/mipsconfig.h
+ * include/asm-mips/mipsconfig.h
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Waldorf Electronics
- * written by Ralf Baechle
- *
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
-#ifndef __ASM_MIPS_MIPS_CONFIG_H
-#define __ASM_MIPS_MIPS_CONFIG_H
+#ifndef __ASM_MIPS_MIPSCONFIG_H
+#define __ASM_MIPS_MIPSCONFIG_H
 
 /*
  * This is the virtual address to which all ports are being mapped.
  * Must be a value that can be load with a lui instruction.
  */
-#define PORT_BASE              0xe0000000
-
-/* #define NUMBER_OF_TLB_ENTRIES       48  */ /* see bootinfo.h -- Andy */
-#define NUMBER_OF_TLB_ENTRIES  48
+#ifndef PORT_BASE
+#define PORT_BASE              0xe2000000
+#endif
 
 /*
- * Pagetables are 4MB mapped at 0xe3000000
- * Must be a value that can be load with a lui instruction.
+ * Pagetables are 4MB mapped at 0xe4000000
+ * Must be a value that can be loaded with a single instruction.
  */
 #define TLBMAP                 0xe4000000
 
  * The virtual address where we'll map the pagetables
  * For a base address of 0xe3000000 this is 0xe338c000
  * For a base address of 0xe4000000 this is 0xe4390000
- * FIXME: Gas miscomputes the following expression!
+ * FIXME: Gas computes the following expression with signed
+ *        shift and therefore false
 #define TLB_ROOT               (TLBMAP + (TLBMAP >> (12-2)))
  */
 #define TLB_ROOT               0xe4390000
 
 /*
- * This ASID is reserved for the swapper
+ * Use this to activate extra TLB error checking
+ */
+#define CONF_DEBUG_TLB
+
+/*
+ * Use this to activate extra TLB profiling code
+ * (currently not implemented)
+ */
+#undef CONF_PROFILE_TLB
+
+/*
+ * Disable all caching.  Usefull to find trouble with caches in drivers.
+ */
+#undef CONF_DISABLE_KSEG0_CACHING
+
+/*
+ * Set this to one to enable additional vdma debug code.
  */
-#define SWAPPER_ASID           0
+#define CONF_DEBUG_VDMA 0
 
-#endif /* __ASM_MIPS_MIPS_CONFIG_H */
+#endif /* __ASM_MIPS_MIPSCONFIG_H */
index b5655c966ca1df28b91a9fff260d8c6cf1c59508..96b9ba21325b929537db16bb3070af6b9d6930ed 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
 
 #ifndef __ASM_MIPS_MIPSREGS_H
@@ -26,9 +26,7 @@
 /*
  * On the R2000/3000 load instructions are not interlocked -
  * we therefore sometimes need to fill load delay slots with a nop
- * which are useless for >=R4000.
- *
- * FIXME: Don't know about R6000
+ * which would be useless for ISA >= 2.
  */
 #if !defined (__R4000__)
 #define FILL_LDS nop
 #define CP0_WATCHLO $18
 #define CP0_WATCHHI $19
 #define CP0_XCONTEXT $20
+#define CP0_FRAMEMASK $21
+#define CP0_DIAGNOSTIC $22
+#define CP0_PERFORMANCE $25
 #define CP0_ECC $26
 #define CP0_CACHEERR $27
 #define CP0_TAGLO $28
 #define CP0_TAGHI $29
 #define CP0_ERROREPC $30
 
+/*
+ * Coprocessor 1 (FPU) register names
+ */
+#define CP1_REVISION   $0
+#define CP1_STATUS     $31
+
 /*
  * Values for PageMask register
  */
 #define PL_4M   22
 #define PL_16M  24
 
-/*
- * Compute a vpn/pfn entry for EntryHi register
- */
-#define VPN(addr,pagesizeshift) ((addr) & ~((1 << (pagesizeshift))-1))
-#define PFN(addr,pagesizeshift) (((addr) & ((1 << (pagesizeshift))-1)) << 6)
-
 /*
  * Macros to access the system control coprocessor
  */
-#define read_32bit_cp0_register(source)                                        \
-({ int __res;                                                                  \
-        __asm__ __volatile__(                                                  \
-        "mfc0\t%0,"STR(source)                                                 \
-        : "=r" (__res));                                                       \
+#define read_32bit_cp0_register(source)                         \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+        "mfc0\t%0,"STR(source)                                  \
+        : "=r" (__res));                                        \
         __res;})
 
-#define read_64bit_cp0_register(source)                                        \
-({ int __res;                                                                  \
-        __asm__ __volatile__(                                                  \
-        "dmfc0\t%0,"STR(source)                                                \
-        : "=r" (__res));                                                       \
+#define read_64bit_cp0_register(source)                         \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+        ".set\tmips3\n\t"                                       \
+        "dmfc0\t%0,"STR(source)"\n\t"                           \
+        ".set\tmips0"                                           \
+        : "=r" (__res));                                        \
         __res;})
 
-#define write_32bit_cp0_register(register,value)                               \
-        __asm__ __volatile__(                                                  \
-        "mtc0\t%0,"STR(register)                                               \
+#define write_32bit_cp0_register(register,value)                \
+        __asm__ __volatile__(                                   \
+        "mtc0\t%0,"STR(register)                                \
         : : "r" (value));
 
+#define write_64bit_cp0_register(register,value)                \
+        __asm__ __volatile__(                                   \
+        ".set\tmips3\n\t"                                       \
+        "dmtc0\t%0,"STR(register)"\n\t"                         \
+        ".set\tmips0"                                           \
+        : : "r" (value))
+/*
+ * R4x00 interrupt enable / cause bits
+ */
+#define IE_SW0          (1<< 8)
+#define IE_SW1          (1<< 9)
+#define IE_IRQ0         (1<<10)
+#define IE_IRQ1         (1<<11)
+#define IE_IRQ2         (1<<12)
+#define IE_IRQ3         (1<<13)
+#define IE_IRQ4         (1<<14)
+#define IE_IRQ5         (1<<15)
+
+/*
+ * R4x00 interrupt cause bits
+ */
+#define C_SW0           (1<< 8)
+#define C_SW1           (1<< 9)
+#define C_IRQ0          (1<<10)
+#define C_IRQ1          (1<<11)
+#define C_IRQ2          (1<<12)
+#define C_IRQ3          (1<<13)
+#define C_IRQ4          (1<<14)
+#define C_IRQ5          (1<<15)
+
+#ifndef __LANGUAGE_ASSEMBLY__
+/*
+ * Manipulate the status register.
+ * Mostly used to access the interrupt bits.
+ */
+#define BUILD_SET_CP0(name,register)                            \
+extern __inline__ unsigned int                                  \
+set_cp0_##name(unsigned int change, unsigned int new)           \
+{                                                               \
+       unsigned int res;                                       \
+                                                                \
+       res = read_32bit_cp0_register(register);                \
+       res &= ~change;                                         \
+       res |= (new & change);                                  \
+       if(change)                                              \
+               write_32bit_cp0_register(register, res);        \
+                                                                \
+       return res;                                             \
+}
+
+BUILD_SET_CP0(status,CP0_STATUS)
+BUILD_SET_CP0(cause,CP0_CAUSE)
+
+#endif /* defined (__LANGUAGE_ASSEMBLY__) */
+
 /*
  * Inline code for use of the ll and sc instructions
  *
  * Since these operations are only being used for atomic operations
  * the easiest workaround for the R[23]00 is to disable interrupts.
  */
-#define load_linked(addr)                                                      \
-({                                                                             \
-       unsigned int __res;                                                    \
-                                                                               \
-       __asm__ __volatile__(                                                  \
-       "ll\t%0,(%1)"                                                          \
-       : "=r" (__res)                                                         \
-       : "r" ((unsigned int) (addr)));                                        \
-                                                                               \
-       __res;                                                                 \
+#define load_linked(addr)                                       \
+({                                                              \
+       unsigned int __res;                                     \
+                                                                \
+       __asm__ __volatile__(                                   \
+       "ll\t%0,(%1)"                                           \
+       : "=r" (__res)                                          \
+       : "r" ((unsigned int) (addr)));                         \
+                                                                \
+       __res;                                                  \
 })
 
-#define store_conditional(addr,value)                                          \
-({                                                                             \
-       int     __res;                                                         \
-                                                                               \
-       __asm__ __volatile__(                                                  \
-       "sc\t%0,(%2)"                                                          \
-       : "=r" (__res)                                                         \
-       : "0" (value), "r" (addr));                                            \
-                                                                               \
-       __res;                                                                 \
+#define store_conditional(addr,value)                           \
+({                                                              \
+       int     __res;                                          \
+                                                                \
+       __asm__ __volatile__(                                   \
+       "sc\t%0,(%2)"                                           \
+       : "=r" (__res)                                          \
+       : "0" (value), "r" (addr));                             \
+                                                                \
+       __res;                                                  \
 })
 
 /*
  * Bitfields in the cp0 status register
  *
- * Refer to MIPS R4600 manual, page 5-4 for explanation
+ * Refer to the MIPS R4xx0 manuals, chapter 5 for explanation.
+ * FIXME: This doesn't cover all R4xx0 processors.
+ */
+#define ST0_IE                 (1   <<  0)
+#define ST0_EXL                        (1   <<  1)
+#define ST0_ERL                        (1   <<  2)
+#define ST0_KSU                        (3   <<  3)
+#  define KSU_USER             (2  <<   3)
+#  define KSU_SUPERVISOR       (1  <<   3)
+#  define KSU_KERNEL           (0  <<   3)
+#define ST0_UX                 (1   <<  5)
+#define ST0_SX                 (1   <<  6)
+#define ST0_KX                         (1   <<  7)
+#define ST0_IM                 (255 <<  8)
+#define ST0_DE                 (1   << 16)
+#define ST0_CE                 (1   << 17)
+#define ST0_CH                 (1   << 18)
+#define ST0_SR                 (1   << 20)
+#define ST0_BEV                        (1   << 22)
+#define ST0_RE                 (1   << 25)
+#define ST0_FR                 (1   << 26)
+#define ST0_CU                 (15  << 28)
+#define ST0_CU0                        (1   << 28)
+#define ST0_CU1                        (1   << 29)
+#define ST0_CU2                        (1   << 30)
+#define ST0_CU3                        (1   << 31)
+#define ST0_XX                 (1   << 31)     /* R8000/R10000 naming */
+
+/*
+ * Bitfields and bit numbers in the coprocessor 0 cause register.
+ *
+ * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
-#define ST0_IE  (1   <<  0)
-#define ST0_EXL (1   <<  1)
-#define ST0_ERL (1   <<  2)
-#define ST0_KSU (3   <<  3)
-#define ST0_UX  (1   <<  5)
-#define ST0_SX  (1   <<  6)
-#define ST0_KX  (1   <<  7)
-#define ST0_IM  (255 <<  8)
-#define ST0_DE  (1   << 16)
-#define ST0_CE  (1   << 17)
-#define ST0_CH  (1   << 18)
-#define ST0_SR  (1   << 20)
-#define ST0_BEV (1   << 22)
-#define ST0_RE  (1   << 25)
-#define ST0_FR  (1   << 26)
-#define ST0_CU  (15  << 28)
-#define ST0_CU0 (1   << 28)
-#define ST0_CU1 (1   << 29)
-#define ST0_CU2 (1   << 30)
-#define ST0_CU3 (1   << 31)
+#define  CAUSEB_EXCCODE                2
+#define  CAUSEF_EXCCODE                (31  <<  2)
+#define  CAUSEB_IP             8
+#define  CAUSEF_IP             (255 <<  8)
+#define  CAUSEB_IP0            8
+#define  CAUSEF_IP0            (1   <<  8)
+#define  CAUSEB_IP1            9
+#define  CAUSEF_IP1            (1   <<  9)
+#define  CAUSEB_IP2            10
+#define  CAUSEF_IP2            (1   << 10)
+#define  CAUSEB_IP3            11
+#define  CAUSEF_IP3            (1   << 11)
+#define  CAUSEB_IP4            12
+#define  CAUSEF_IP4            (1   << 12)
+#define  CAUSEB_IP5            13
+#define  CAUSEF_IP5            (1   << 13)
+#define  CAUSEB_IP6            14
+#define  CAUSEF_IP6            (1   << 14)
+#define  CAUSEB_IP7            15
+#define  CAUSEF_IP7            (1   << 15)
+#define  CAUSEB_CE             28
+#define  CAUSEF_CE             (3   << 28)
+#define  CAUSEB_BD             31
+#define  CAUSEF_BD             (1   << 31)
 
 #endif /* __ASM_MIPS_MIPSREGS_H */
diff --git a/include/asm-mips/mman.h b/include/asm-mips/mman.h
new file mode 100644 (file)
index 0000000..292fd7b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Linux/MIPS memory manager definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_MMAN_H
+#define __ASM_MIPS_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together.  The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ.  The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+#define PROT_NONE      0x0             /* page can not be accessed */
+#define PROT_READ      0x1             /* page can be read */
+#define PROT_WRITE     0x2             /* page can be written */
+#define PROT_EXEC      0x4             /* page can be executed */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED     0x001           /* Share changes */
+#define MAP_PRIVATE    0x002           /* Changes are private */
+#define MAP_TYPE       0x00f           /* Mask for type of mapping */
+#define MAP_FIXED      0x010           /* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME     0x020           /* Assign page to file */
+#define MAP_AUTOGROW   0x040           /* File may grow by writing */
+#define MAP_LOCAL      0x080           /* Copy on fork/sproc */
+#define MAP_AUTORSRV   0x100           /* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_ANONYMOUS  0x0800          /* don't use a file */
+#define MAP_GROWSDOWN  0x1000          /* stack-like segment */
+#define MAP_DENYWRITE  0x2000          /* ETXTBSY */
+#define MAP_EXECUTABLE 0x4000          /* mark it as a executable */
+#define MAP_LOCKED     0x8000          /* pages are locked */
+
+/*
+ * Flags for msync
+ */
+#define MS_SYNC                0               /* synchronous memory sync */
+#define MS_ASYNC       1               /* sync memory asynchronously */
+#define MS_INVALIDATE  2               /* invalidate mappings & caches */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT    1               /* lock all current mappings */
+#define MCL_FUTURE     2               /* lock all future mappings */
+
+/* compatibility flags */
+#define MAP_ANON       MAP_ANONYMOUS
+#define MAP_FILE       0
+
+#endif /* __ASM_MIPS_MMAN_H */
index 16acc0260c19ccd8504756785545fa79e881a625..59a9dfa5d6cfe1fb886434a8ffdacb042ec4cf49 100644 (file)
@@ -1,36 +1,33 @@
 #ifndef __ASM_MIPS_PAGE_H
 #define __ASM_MIPS_PAGE_H
 
-#define STRICT_MM_TYPECHECKS
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT     12
+#define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#define PAGE_MASK      (~(PAGE_SIZE-1))
 
-#define invalidate()   tlbflush();
-extern asmlinkage void tlbflush(void);
+#ifdef __KERNEL__
 
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define STRICT_MM_TYPECHECKS
 
-typedef unsigned short mem_map_t;
+#ifndef __LANGUAGE_ASSEMBLY__
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
  */
 typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pte_val(x)     ((x).pte)
+#define pmd_val(x)     ((x).pmd)
 #define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
 
 #define __pte(x)       ((pte_t) { (x) } )
+#define __pme(x)       ((pme_t) { (x) } )
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
@@ -39,202 +36,67 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  * .. while these make it easier on the compiler
  */
 typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
 typedef unsigned long pgd_t;
 typedef unsigned long pgprot_t;
 
 #define pte_val(x)     (x)
+#define pmd_val(x)     (x)
 #define pgd_val(x)     (x)
 #define pgprot_val(x)  (x)
 
 #define __pte(x)       (x)
+#define __pmd(x)       (x)
 #define __pgd(x)       (x)
 #define __pgprot(x)    (x)
 
 #endif /* !defined (STRICT_MM_TYPECHECKS) */
-#endif /* __ASSEMBLY__ */
-
-/*
- * Note that we shift the lower 32bits of each EntryLo[01] entry
- * 6 bits to the left. That way we can convert the PFN into the
- * physical address by a single 'and' operation and gain 6 additional
- * bits for storing information which isn't present in a normal
- * MIPS page table.
- */
-#define _PAGE_PRESENT               (1<<0)  /* implemented in software */
-#define _PAGE_COW                   (1<<1)  /* implemented in software */
-#define _PAGE_DIRTY                 (1<<2)  /* implemented in software */
-#define _PAGE_USER                  (1<<3)
-#define _PAGE_UNUSED1               (1<<4)
-#define _PAGE_UNUSED2               (1<<5)
-#define _PAGE_GLOBAL                (1<<6)
-#define _PAGE_ACCESSED              (1<<7)   /* The MIPS valid bit      */
-#define _PAGE_RW                    (1<<8)   /* The MIPS dirty bit      */
-#define _CACHE_CACHABLE_NO_WA       (0<<9)
-#define _CACHE_CACHABLE_WA          (1<<9)
-#define _CACHE_UNCACHED             (2<<9)
-#define _CACHE_CACHABLE_NONCOHERENT (3<<9)
-#define _CACHE_CACHABLE_CE          (4<<9)
-#define _CACHE_CACHABLE_COW         (5<<9)
-#define _CACHE_CACHABLE_CUW         (6<<9)
-#define _CACHE_MASK                 (7<<9)
-
-#define _PAGE_TABLE     (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY | \
-                         _CACHE_CACHABLE_NO_WA)
-
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
-
-#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _CACHE_CACHABLE_NO_WA)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW | _CACHE_CACHABLE_NO_WA)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _CACHE_CACHABLE_NO_WA)
-#define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
 
 /*
- * MIPS can't do page protection for execute, and considers that the same like
- * read. Also, write permissions imply read permissions. This is the closest
- * we can get by reasonable means..
+ * We need a special version of copy_page that can handle virtual caches.
+ * While we're at tweaking with caches we can use that to make it even
+ * faster.  The R10000 accelerated caching mode will further accelerate it.
  */
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
-
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT                     12
-#define PGDIR_SHIFT                    22
-#define PAGE_SIZE                      (1UL << PAGE_SHIFT)
-#define PGDIR_SIZE                     (1UL << PGDIR_SHIFT)
-
-#ifdef __KERNEL__
+extern void __copy_page(unsigned long from, unsigned long to);
+#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
 
-#define PAGE_OFFSET    KERNELBASE
-#define MAP_NR(addr)   (((addr) - PAGE_OFFSET) >> PAGE_SHIFT)
-#define MAP_PAGE_RESERVED (1<<15)
-
-#if !defined (__ASSEMBLY__)
-
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
-
-/*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-
-extern unsigned long __zero_page(void);
-
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
-
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR                   (8*sizeof(unsigned long))
-
-/* to mask away the intra-page address bits */
-#define PAGE_MASK                      (~(PAGE_SIZE-1))
-
-/* to mask away the intra-page address bits */
-#define PGDIR_MASK                     (~(PGDIR_SIZE-1))
+#endif /* __LANGUAGE_ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)               (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK                       (~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2                        2
-
-/* to find an entry in a page-table-directory */
-#define PAGE_DIR_OFFSET(tsk,address) \
-((((unsigned long)(address)) >> PGDIR_SHIFT) + (pgd_t *) (tsk)->tss.pg_dir)
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((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*))
-
-/* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
-       (tsk)->tss.pg_dir = (unsigned long) (pgdir); \
-       if ((tsk) == current) \
-               invalidate(); \
-} while (0)
-
-extern unsigned long high_memory;
-
-extern inline int pte_none(pte_t pte)          { return !pte_val(pte); }
-extern inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
-
-extern inline int pgd_none(pgd_t pgd)          { return !pgd_val(pgd); }
-extern inline int pgd_bad(pgd_t pgd)           { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
-extern inline int pgd_present(pgd_t pgd)       { return pgd_val(pgd) & _PAGE_PRESENT; }
-extern inline void pgd_clear(pgd_t * pgdp)     { pgd_val(*pgdp) = 0; }
+#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
+/* This handles the memory map */
+#if __mips == 3
 /*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
+ * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent)
+ * Pagetables are at  XKPHYS + 0x1000000000000000 (uncached)
  */
-extern inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
-extern inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_cow(pte_t pte)           { return pte_val(pte) & _PAGE_COW; }
-
-extern inline pte_t pte_wrprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte)     { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte)       { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_uncow(pte_t pte)       { pte_val(pte) &= ~_PAGE_COW; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte)     { pte_val(pte) |= _PAGE_RW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)      { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)      { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte)     { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte)     { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkcow(pte_t pte)       { pte_val(pte) |= _PAGE_COW; return pte; }
-
+#define PAGE_OFFSET    0x9800000000000000UL
+#define PT_OFFSET      0x9000000000000000UL
+#define MAP_MASK        0x07ffffffffffffffUL
+#else
 /*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
+ * We handle pages at KSEG0 (cachable, noncoherent)
+ * Pagetables are at  KSEG1 (uncached)
  */
-extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
+#define PAGE_OFFSET    0x80000000
+#define PT_OFFSET      0xa0000000
+#define MAP_MASK        0x1fffffff
+#endif
+
+#define MAP_NR(addr)   ((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT)
 
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+#ifndef __LANGUAGE_ASSEMBLY__
 
-extern inline unsigned long pte_page(pte_t pte)        { return pte_val(pte) & PAGE_MASK; }
-extern inline unsigned long pgd_page(pgd_t pgd)        { return pgd_val(pgd) & PAGE_MASK; }
+extern unsigned long page_colour_mask;
 
-extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
-{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; }
+extern inline unsigned long
+page_colour(unsigned long page)
+{
+       return page & page_colour_mask;
+}
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* defined (__LANGUAGE_ASSEMBLY__) */
 #endif /* defined (__KERNEL__) */
 
 #endif /* __ASM_MIPS_PAGE_H */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
new file mode 100644 (file)
index 0000000..ba28bc1
--- /dev/null
@@ -0,0 +1,570 @@
+#ifndef __ASM_MIPS_PGTABLE_H
+#define __ASM_MIPS_PGTABLE_H
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/cachectl.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. In
+ * 32 bit mode we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * i386 mmu expects. The 64 bit version uses a three level setup.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the MIPS page table tree.  Note the frequent conversion between addresses
+ * in KSEG0 and KSEG1.
+ *
+ * This is required due to the cache aliasing problem of the R4xx0 series.
+ * Sometimes doing uncached accesses also to improve the cache performance
+ * slightly.  The R10000 caching mode "uncached accelerated" will help even
+ * further.
+ */
+
+/*
+ * TLB invalidation:
+ *
+ *  - invalidate() invalidates the current mm struct TLBs
+ *  - invalidate_all() invalidates all processes TLBs
+ *  - invalidate_mm(mm) invalidates the specified mm context TLB's
+ *  - invalidate_page(mm, vmaddr) invalidates one page
+ *  - invalidate_range(mm, start, end) invalidates a range of pages
+ *
+ * FIXME: MIPS has full control of all TLB activity in the CPU.  Though
+ * we just stick with complete flushing of TLBs for now.
+ */
+extern asmlinkage void tlbflush(void);
+#define invalidate()   ({sys_cacheflush(0, ~0, BCACHE);tlbflush();})
+
+#define invalidate_all() invalidate()
+#define invalidate_mm(mm_struct) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+#define invalidate_page(mm_struct,addr) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+#define invalidate_range(mm_struct,start,end) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+
+/*
+ * We need a special version of copy_page that can handle virtual caches.
+ * While we're at tweaking with caches we can use that to make it faster.
+ * The R10000's accelerated caching mode will further accelerate it.
+ */
+extern void __copy_page(unsigned long from, unsigned long to);
+#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT      22
+#define PMD_SIZE       (1UL << PMD_SHIFT)
+#define PMD_MASK       (~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT    22
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK     (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: we use two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE   1024
+#define PTRS_PER_PMD   1
+#define PTRS_PER_PGD   1024
+
+#define VMALLOC_START     KSEG2
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+/*
+ * Note that we shift the lower 32bits of each EntryLo[01] entry
+ * 6 bits to the left. That way we can convert the PFN into the
+ * physical address by a single 'and' operation and gain 6 additional
+ * bits for storing information which isn't present in a normal
+ * MIPS page table.
+ * Since the Mips has choosen some quite missleading names for the
+ * valid and dirty bits they're defined here but only their synonyms
+ * will be used.
+ */
+#define _PAGE_PRESENT               (1<<0)  /* implemented in software */
+#define _PAGE_COW                   (1<<1)  /* implemented in software */
+#define _PAGE_READ                  (1<<2)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<3)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<4)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<5)  /* implemented in software */
+#define _PAGE_GLOBAL                (1<<6)
+#define _PAGE_VALID                 (1<<7)
+#define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<8)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<8)
+#define _CACHE_CACHABLE_NO_WA       (0<<9)  /* R4600 only              */
+#define _CACHE_CACHABLE_WA          (1<<9)  /* R4600 only              */
+#define _CACHE_UNCACHED             (2<<9)  /* R4[0246]00              */
+#define _CACHE_CACHABLE_NONCOHERENT (3<<9)  /* R4[0246]00              */
+#define _CACHE_CACHABLE_CE          (4<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_COW         (5<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_CUW         (6<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_ACCELERATED (7<<9)  /* R10000 only             */
+#define _CACHE_MASK                 (7<<9)
+
+#define __READABLE     (_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED)
+#define __WRITEABLE    (_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED)
+
+#define _PAGE_TABLE    (_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+                       _PAGE_DIRTY | _CACHE_UNCACHED)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
+
+#define PAGE_NONE      __pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+                       _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \
+                       _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | __READABLE | \
+                       _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+                       _CACHE_CACHABLE_NONCOHERENT)
+
+/*
+ * MIPS can't do page protection for execute, and considers that the same like
+ * read. Also, write permissions imply read permissions. This is the closest
+ * we can get by reasonable means..
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+#if !defined (__LANGUAGE_ASSEMBLY__)
+
+/* page table for 0-4MB for everybody */
+extern unsigned long pg0[1024];
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+extern unsigned long __zero_page(void);
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE __zero_page()
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR                   (8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK                       (~(sizeof(void*)-1))
+
+/*
+ * sizeof(void*)==1<<SIZEOF_PTR_LOG2
+ */
+#if __mips == 3
+#define SIZEOF_PTR_LOG2                        3
+#else
+#define SIZEOF_PTR_LOG2                        2
+#endif
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk,pgdir) \
+do { \
+       (tsk)->tss.pg_dir = ((unsigned long) (pgdir)) - PT_OFFSET; \
+       if ((tsk) == current) \
+       { \
+               void load_pgd(unsigned long pg_dir); \
+ \
+               load_pgd((tsk)->tss.pg_dir); \
+       } \
+} while (0)
+
+extern unsigned long high_memory;
+extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline unsigned long pte_page(pte_t pte)
+{ return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK); }
+
+extern inline unsigned long pmd_page(pmd_t pmd)
+{ return PAGE_OFFSET + (pmd_val(pmd) & PAGE_MASK); }
+
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{ pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); }
+
+extern inline int pte_none(pte_t pte)          { return !pte_val(pte); }
+extern inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_inuse(pte_t *ptep)       { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
+extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+       if (!mem_map[MAP_NR(ptep)].reserved)
+               mem_map[MAP_NR(ptep)].count++;
+}
+
+/*
+ * Empty pgd/pmd entries point to the invalid_pte_table.
+ */
+extern inline int pmd_none(pmd_t pmd)          { return (pmd_val(pmd) & PAGE_MASK) == ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
+
+extern inline int pmd_bad(pmd_t pmd)
+{
+       return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE ||
+               pmd_page(pmd) > high_memory ||
+               pmd_page(pmd) < PAGE_OFFSET;
+}
+extern inline int pmd_present(pmd_t pmd)       { return pmd_val(pmd) & _PAGE_PRESENT; }
+extern inline int pmd_inuse(pmd_t *pmdp)       { return 0; }
+extern inline void pmd_clear(pmd_t * pmdp)     { pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
+extern inline void pmd_reuse(pmd_t * pmdp)     { }
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd)          { return 0; }
+extern inline int pgd_bad(pgd_t pgd)           { return 0; }
+extern inline int pgd_present(pgd_t pgd)       { return 1; }
+extern inline int pgd_inuse(pgd_t * pgdp)      { return mem_map[MAP_NR(pgdp)].reserved; }
+extern inline void pgd_clear(pgd_t * pgdp)     { }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_cow(pte_t pte)           { return pte_val(pte) & _PAGE_COW; }
+
+extern inline pte_t pte_wrprotect(pte_t pte)
+{
+       pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+       return pte;
+}
+extern inline pte_t pte_rdprotect(pte_t pte)
+{
+       pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+}
+extern inline pte_t pte_exprotect(pte_t pte)
+{
+       pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+}
+extern inline pte_t pte_mkclean(pte_t pte)     { pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); return pte; }
+extern inline pte_t pte_mkold(pte_t pte)       { pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); return pte; }
+extern inline pte_t pte_uncow(pte_t pte)       { pte_val(pte) &= ~_PAGE_COW; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_WRITE;
+       if (pte_val(pte) & _PAGE_MODIFIED)
+               pte_val(pte) |= _PAGE_SILENT_WRITE;
+       return pte;
+}
+extern inline pte_t pte_mkread(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_READ;
+       if (pte_val(pte) & _PAGE_ACCESSED)
+               pte_val(pte) |= _PAGE_SILENT_READ;
+       return pte;
+}
+extern inline pte_t pte_mkexec(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_READ;
+       if (pte_val(pte) & _PAGE_ACCESSED)
+               pte_val(pte) |= _PAGE_SILENT_READ;
+       return pte;
+}
+extern inline pte_t pte_mkdirty(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_MODIFIED;
+       if (pte_val(pte) & _PAGE_WRITE)
+               pte_val(pte) |= _PAGE_SILENT_WRITE;
+       return pte;
+}
+extern inline pte_t pte_mkyoung(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_ACCESSED;
+       if (pte_val(pte) & _PAGE_READ)
+       {
+               pte_val(pte) |= _PAGE_SILENT_READ;
+               if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == (_PAGE_WRITE|_PAGE_MODIFIED))
+                       pte_val(pte) |= _PAGE_SILENT_WRITE;
+       }
+       return pte;
+}
+extern inline pte_t pte_mkcow(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_COW;
+       return pte;
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{ pte_t pte; pte_val(pte) = (page - PAGE_OFFSET) | pgprot_val(pgprot); return pte; }
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+       return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+       return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */ 
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+       return (pte_t *) (pmd_page(*dir) + (PT_OFFSET - PAGE_OFFSET)) +
+              ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+extern inline void pte_free_kernel(pte_t * pte)
+{
+       unsigned long page = (unsigned long) pte;
+
+       mem_map[MAP_NR(pte)].reserved = 0;
+       if(!page)
+               return;
+       page -= (PT_OFFSET - PAGE_OFFSET);
+       free_page(page);
+}
+
+extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               unsigned long page = __get_free_page(GFP_KERNEL);
+               if (pmd_none(*pmd)) {
+                       if (page) {
+                               mem_map[MAP_NR(page)].reserved = 1;
+                               memset((void *) page, 0, PAGE_SIZE);
+                               sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+                               sync_mem();
+                               page += (PT_OFFSET - PAGE_OFFSET);
+                               pmd_set(pmd, (pte_t *)page);
+                               return ((pte_t *)page) + address;
+                       }
+                       pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+                       return NULL;
+               }
+               free_page(page);
+       }
+       if (pmd_bad(*pmd)) {
+               printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+               pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+               return NULL;
+       }
+       return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+       return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+       unsigned long page = (unsigned long) pte;
+
+       if(!page)
+               return;
+       page -= (PT_OFFSET - PAGE_OFFSET);
+       free_page(page);
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               unsigned long page = __get_free_page(GFP_KERNEL);
+               if (pmd_none(*pmd)) {
+                       if (page) {
+                               memset((void *) page, 0, PAGE_SIZE);
+                               sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+                               sync_mem();
+                               page += (PT_OFFSET - PAGE_OFFSET);
+                               pmd_set(pmd, (pte_t *)page);
+                               return ((pte_t *)page) + address;
+                       }
+                       pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+                       return NULL;
+               }
+               free_page(page);
+       }
+       if (pmd_bad(*pmd)) {
+               printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+               pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+               return NULL;
+       }
+       return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+       return (pmd_t *) pgd;
+}
+
+extern inline void pgd_free(pgd_t * pgd)
+{
+       unsigned long page = (unsigned long) pgd;
+
+       if(!page)
+               return;
+       page -= (PT_OFFSET - PAGE_OFFSET);
+       free_page(page);
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+extern inline void pgd_init(unsigned long page)
+{
+       unsigned long dummy1, dummy2;
+
+       page += (PT_OFFSET - PAGE_OFFSET);
+#if __mips >= 3
+       /*
+        * Ich will Spass - ich geb Gas ich geb Gas...
+        */
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               ".set\tnoat\n\t"
+               ".set\tmips3\n\t"
+               "dsll32\t$1,%2,0\n\t"
+               "dsrl32\t%2,$1,0\n\t"
+               "or\t%2,$1\n"
+               "1:\tsd\t%2,(%0)\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,8\n\t"
+               ".set\tmips0\n\t"
+               ".set\tat\n\t"
+               ".set\treorder"
+               :"=r" (dummy1),
+                "=r" (dummy2)
+               :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
+                      _PAGE_TABLE),
+                "0" (page),
+                "1" (PAGE_SIZE/(sizeof(pmd_t)*2))
+               :"$1");
+#else
+       __asm__ __volatile__(
+               ".set\tnoreorder\n"
+               "1:\tsw\t%2,(%0)\n\t"
+               "subu\t%1,1\n\t"
+               "bnez\t%1,1b\n\t"
+               "addiu\t%0,4\n\t"
+               ".set\treorder"
+               :"=r" (dummy1),
+                "=r" (dummy2)
+               :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
+                      _PAGE_TABLE),
+                "0" (page),
+                "1" (PAGE_SIZE/sizeof(pmd_t)));
+#endif
+}
+
+extern inline pgd_t * pgd_alloc(void)
+{
+       unsigned long page;
+
+       if(!(page = __get_free_page(GFP_KERNEL)))
+               return NULL;
+
+       sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+       sync_mem();
+       pgd_init(page);
+
+       return (pgd_t *) (page + (PT_OFFSET - PAGE_OFFSET));
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * MIPS doesn't need any external MMU info: the kernel page tables contain
+ * all the necessary information.  We use this hook though to load the
+ * TLB as early as possible with uptodate information avoiding unecessary
+ * exceptions.
+ */
+extern void update_mmu_cache(struct vm_area_struct * vma,
+       unsigned long address, pte_t pte);
+
+#if __mips >= 3
+
+#define SWP_TYPE(entry) (((entry) >> 32) & 0xff)
+#define SWP_OFFSET(entry) ((entry) >> 40)
+#define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
+
+#else
+
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+
+#endif
+
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+#endif /* __ASM_MIPS_PGTABLE_H */
diff --git a/include/asm-mips/pica.h b/include/asm-mips/pica.h
new file mode 100644 (file)
index 0000000..799dcf4
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Hardware info about Acer PICA 61 and similar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Andreas Busse and Ralf Baechle
+ */
+#ifndef __ASM_MIPS_PICA_H 
+#define __ASM_MIPS_PICA_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb. The Mips
+ * Magnum R3000 and R4000 machines are similar in many aspects,
+ * but many hardware register are accessible at 0xb9000000 in
+ * instead of 0xe0000000.
+ */
+
+/*
+ * Revision numbers in PICA_ASIC_REVISION
+ *
+ * 0xf0000000 - Rev1
+ * 0xf0000001 - Rev2
+ * 0xf0000002 - Rev3
+ */
+#define PICA_ASIC_REVISION      0xe0000008
+
+/*
+ * The segments of the seven segment LED are mapped
+ * to the control bits as follows:
+ *
+ *         (7)
+ *      ---------
+ *      |       |
+ *  (2) |       | (6)
+ *      |  (1)  |
+ *      ---------
+ *      |       |
+ *  (3) |       | (5)
+ *      |  (4)  |
+ *      --------- . (0)
+ */
+#define PICA_LED                0xe000f000
+
+/*
+ * Some characters for the LED control registers
+ * The original Mips machines seem to have a LED display
+ * with integrated decoder while the Acer machines can
+ * control each of the seven segments and the dot independend.
+ * It only a toy, anyway...
+ */
+#define LED_DOT                 0x01
+#define LED_SPACE               0x00
+#define LED_0                   0xfc
+#define LED_1                   0x60
+#define LED_2                   0xda
+#define LED_3                   0xf2
+#define LED_4                   0x66
+#define LED_5                   0xb6
+#define LED_6                   0xbe
+#define LED_7                   0xe0
+#define LED_8                   0xfe
+#define LED_9                   0xf6
+#define LED_A                   0xee
+#define LED_b                   0x3e
+#define LED_C                   0x9c
+#define LED_d                   0x7a
+#define LED_E                   0x9e
+#define LED_F                   0x8e
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pica_set_led(unsigned int bits)
+{
+       volatile unsigned int *led_register = (unsigned int *) PICA_LED;
+
+       *led_register = bits;
+}
+
+#endif
+
+/*
+ * i8042 keyboard controller for PICA chipset.
+ * This address is just a guess and seems to differ
+ * from the other mips machines...
+ */
+#define PICA_KEYBOARD_ADDRESS   0xe0005000
+#define PICA_KEYBOARD_DATA      0xe0005000
+#define PICA_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+       unsigned char data;
+       unsigned char command;
+} pica_keyboard_hardware;
+
+typedef struct {
+       unsigned char pad0[3];
+       unsigned char data;
+       unsigned char pad1[3];
+       unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now
+ */
+#define keyboard_hardware       pica_keyboard_hardware
+
+#endif
+
+/*
+ * i8042 keyboard controller for most other Mips machines.
+ */
+#define MIPS_KEYBOARD_ADDRESS   0xb9005000
+#define MIPS_KEYBOARD_DATA      0xb9005003
+#define MIPS_KEYBOARD_COMMAND   0xb9005007
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#endif
+
+/*
+ * PICA timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define PICA_TIMER_INTERVAL     0xe0000228
+#define PICA_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+       unsigned int bank2 : 3;
+       unsigned int bank1 : 3;
+       unsigned int mem_bus_width : 1;
+       unsigned int reserved2 : 1;
+       unsigned int page_mode : 1;
+       unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+       unsigned int reserved1 : 23;
+       unsigned int page_mode : 1;
+       unsigned int reserved2 : 1;
+       unsigned int mem_bus_width : 1;
+       unsigned int bank1 : 3;
+       unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PICA_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * PICA interrupt control registers
+ */
+#define PICA_IO_IRQ_SOURCE      0xe0100000
+#define PICA_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * Pica interrupt enable bits
+ */
+#define PIE_PARALLEL            (1<<0)
+#define PIE_FLOPPY              (1<<1)
+#define PIE_SOUND               (1<<2)
+#define PIE_VIDEO               (1<<3)
+#define PIE_ETHERNET            (1<<4)
+#define PIE_SCSI                (1<<5)
+#define PIE_KEYBOARD            (1<<6)
+#define PIE_MOUSE               (1<<7)
+#define PIE_SERIAL1             (1<<8)
+#define PIE_SERIAL2             (1<<9)
+
+#endif /* __ASM_MIPS_PICA_H */
index 8d587a7d9353874064b7eb1ea82d511be9180029..2deedb245e73515e115a7d5beae82ca4f6b97a94 100644 (file)
@@ -8,7 +8,10 @@
 #ifndef __ASM_MIPS_PROCESSOR_H
 #define __ASM_MIPS_PROCESSOR_H
 
-#if !defined (__ASSEMBLY__)
+#if !defined (__LANGUAGE_ASSEMBLY__)
+#include <asm/cachectl.h>
+#include <asm/mipsregs.h>
+#include <asm/reg.h>
 #include <asm/system.h>
 
 /*
@@ -19,46 +22,6 @@ extern char wait_available;          /* only available on R4[26]00 */
 extern unsigned long intr_count;
 extern unsigned long event;
 
-#if defined (__R4000__)
-
-#define start_bh_atomic()        \
-__asm__ __volatile__(            \
-       ".set\tnoreorder\n\t"    \
-       ".set\tnoat\n\t"         \
-       "ll\t$1,(%0)\n"          \
-       "1:\taddiu\t$1,$1,1\n\t" \
-       "sc\t$1,(%0)\n\t"        \
-       "beqzl\t$1,1b\n\t"       \
-       "ll\t$1,(%0)\n\t"        \
-       ".set\tat\n\t"           \
-       ".set\treorder"          \
-       : /* no outputs */       \
-       : "r" (&intr_count));
-
-#define end_bh_atomic()          \
-__asm__ __volatile__(            \
-       ".set\tnoreorder\n\t"    \
-       ".set\tnoat\n\t"         \
-       "ll\t$1,(%0)\n"          \
-       "1:\tsubu\t$1,$1,1\n\t"  \
-       "sc\t$1,(%0)\n\t"        \
-       "beqzl\t$1,1b\n\t"       \
-       "ll\t$1,(%0)\n\t"        \
-       ".set\tat\n\t"           \
-       ".set\treorder"          \
-       : /* no outputs */       \
-       : "r" (&intr_count));
-
-#else /* !defined (__R4000__) */
-
-#define start_bh_atomic() \
-{int flags; save_flags(flags); cli(); intr_count++; restore_flags(flags)}
-
-#define end_bh_atomic() \
-{int flags; save_flags(flags); cli(); intr_count--; restore_flags(flags)}
-
-#endif
-
 /*
  * Bus types (default is ISA, but people can check others with these..)
  * MCA_bus hardcoded to 0 for now.
@@ -107,7 +70,7 @@ union mips_fpu_union {
 };
 
 #define INIT_FPU { \
-       0, \
+       {{0,},} \
 }
 
 /*
@@ -128,17 +91,18 @@ struct thread_struct {
         */
        union mips_fpu_union fpu;
        /*
-        * Other stuff associated with the process
+        * Other stuff associated with the thread
         */
        unsigned long cp0_badvaddr;
        unsigned long error_code;
        unsigned long trap_no;
        unsigned long ksp;              /* Top of kernel stack   */
-       unsigned long fs;               /* "Segment" pointer     */
        unsigned long pg_dir;           /* L1 page table pointer */
+#define MF_FIXADE 1
+       unsigned long mflags;
 };
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
 /*
  * If you change the #defines remember to change thread_struct above too!
@@ -164,10 +128,13 @@ struct thread_struct {
 #define TOFF_ERROR_CODE                (TOFF_CP0_BADVADDR+4)
 #define TOFF_TRAP_NO           (TOFF_ERROR_CODE+4)
 #define TOFF_KSP               (TOFF_TRAP_NO+4)
-#define TOFF_FS                        (TOFF_KSP+4)
-#define TOFF_PG_DIR            (TOFF_FS+4)
+#define TOFF_PG_DIR            (TOFF_KSP+4)
+#define TOFF_MFLAGS            (TOFF_PG_DIR+4)
 
-#if !defined (__ASSEMBLY__)
+#if !defined (__LANGUAGE_ASSEMBLY__)
+
+#define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
+                    VM_READ | VM_WRITE | VM_EXEC }
 
 #define INIT_TSS  { \
         /* \
@@ -186,8 +153,39 @@ struct thread_struct {
        /* \
         * Other stuff associated with the process\
         */ \
-       0, 0, 0, (((unsigned long)init_kernel_stack)+4096-8), \
-       KERNEL_DS, (unsigned long) swapper_pg_dir \
+       0, 0, 0, sizeof(init_kernel_stack) + (unsigned long)init_kernel_stack - 8, \
+       (unsigned long) swapper_pg_dir - PT_OFFSET, 0 \
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+       return ((unsigned long *)t->reg29)[EF_CP0_EPC];
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+static __inline__
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+{
+       /*
+        * Pure paranoia; probably not needed.
+        */
+       sys_cacheflush(0, ~0, BCACHE);
+       sync_mem();
+       regs->cp0_epc = pc;
+       /*
+        * New thread looses kernel priviledges.
+        */
+       regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
+       /*
+        * Reserve argument save space for registers a0 - a3.
+       regs->reg29 = sp - 4 * sizeof(unsigned long);
+        */
+       regs->reg29 = sp;
 }
 
 #ifdef __KERNEL__
@@ -210,12 +208,21 @@ asmlinkage void resume(struct task_struct *tsk, int offset);
 
 #else /* !defined (__R4000__) */
 
-#error "#define USES_USER_TIME(regs)!"
+#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x4))
 
 #endif /* !defined (__R4000__) */
 
 #endif /* __KERNEL__ */
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+/*
+ * ELF support
+ *
+ * Using EM_MIPS is actually wrong - this one is reserved for big endian
+ * machines only
+ */
+#define INCOMPATIBLE_MACHINE(m) ((m) != EM_MIPS && (m) != EM_MIPS_RS4_BE)
+#define ELF_EM_CPU EM_MIPS
 
 #endif /* __ASM_MIPS_PROCESSOR_H */
index 8f005ac25b047d3c3d1e29d4255412231c5af4d0..a297a1c8a882066d70bea3f6e12a7d8946795020 100644 (file)
@@ -1,34 +1,29 @@
 /*
  * linux/include/asm-mips/ptrace.h
  *
- * machine dependent structs and defines to help the user use
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf GMBH
+ * written by Ralf Baechle
+ *
+ * Machine dependent structs and defines to help the user use
  * the ptrace system call.
  */
 #ifndef __ASM_MIPS_PTRACE_H
 #define __ASM_MIPS_PTRACE_H
 
 /*
- * use ptrace (3 or 6, pid, PT_EXCL, data); to read or write
- * the processes registers.
- *
- * This defines/structures correspond to the register layout on stack -
- * if the order here is changed, it needs to be updated in
- * arch/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
- * asm-mips/ptrace.c, include/asm-mips/ptrace.h.
- */
-
-#include <asm/stackframe.h>
-
-/*
- * This struct defines the way the registers are stored on the 
- * stack during a system call/exception. As usual the registers
- * k0/k1 aren't being saved.
+ * This struct defines the way the registers are stored on the stack during a
+ * system call/exception. As usual the registers k0/k1 aren't being saved.
  */
 struct pt_regs {
        /*
         * Pad bytes for argument save space on the stack
+        * 20/40 Bytes for 32/64 bit code
         */
-       unsigned long pad0[FR_REG1/sizeof(unsigned long)];
+       unsigned long pad0[5];
 
        /*
         * saved main processor registers
@@ -56,19 +51,26 @@ struct pt_regs {
         */
        unsigned long interrupt;
        long orig_reg2;
+       long pad1;
 };
 
+#ifdef __KERNEL__
+
 /*
  * Does the process account for user or for system time?
  */
 #if defined (__R4000__)
 
-#define user_mode(regs) (!((regs)->cp0_status & 0x18))
+#define user_mode(regs) ((regs)->cp0_status & 0x10)
 
 #else /* !defined (__R4000__) */
 
-#error "#define user_mode(regs) for R3000!"
+#define user_mode(regs) (!((regs)->cp0_status & 0x8))
 
 #endif /* !defined (__R4000__) */
 
+#define instruction_pointer(regs) ((regs)->cp0_epc)
+extern void show_regs(struct pt_regs *);
+#endif
+
 #endif /* __ASM_MIPS_PTRACE_H */
diff --git a/include/asm-mips/reg.h b/include/asm-mips/reg.h
new file mode 100644 (file)
index 0000000..701386d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Makefile for MIPS Linux main source directory
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_REG_H
+#define __ASM_MIPS_REG_H
+
+/*
+ * This defines/structures correspond to the register layout on stack -
+ * if the order here is changed, it needs to be updated in
+ * include/asm-mips/stackframe.h
+ */
+#define EF_REG1       5
+#define EF_REG2       6
+#define EF_REG3       7
+#define EF_REG4       8
+#define EF_REG5       9
+#define EF_REG6       10
+#define EF_REG7       11
+#define EF_REG8       12
+#define EF_REG9       13
+#define EF_REG10      14
+#define EF_REG11      15
+#define EF_REG12      16
+#define EF_REG13      17
+#define EF_REG14      18
+#define EF_REG15      19
+#define EF_REG16      20
+#define EF_REG17      21
+#define EF_REG18      22
+#define EF_REG19      23
+#define EF_REG20      24
+#define EF_REG21      25
+#define EF_REG22      26
+#define EF_REG23      27
+#define EF_REG24      28
+#define EF_REG25      29
+/*
+ * k0/k1 unsaved
+ */
+#define EF_REG28      30
+#define EF_REG29      31
+#define EF_REG30      32
+#define EF_REG31      33
+
+/*
+ * Saved special registers
+ */
+#define EF_LO         34
+#define EF_HI         35
+
+/*
+ * saved cp0 registers
+ */
+#define EF_CP0_STATUS 36
+#define EF_CP0_EPC    37
+#define EF_CP0_CAUSE  38
+
+/*
+ * Some goodies
+ */
+#define EF_INTERRUPT  39
+#define EF_ORIG_REG2  40
+
+#define EF_SIZE                (41*4)
+
+/*
+ * Map register number into core file offset.
+ */
+#define CORE_REG(reg, ubase) \
+       (((unsigned long *)((unsigned long)(ubase)))[reg])
+
+#endif /* __ASM_MIPS_REG_H */
index f3eeb8e279800a782df4a1680fa78c62a14b8b24..691d047b676623058a5b917d6363114afb91d85c 100644 (file)
@@ -5,17 +5,17 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
 
-#ifndef __ASM_MIPS_REGSDEFS_H
-#define __ASM_MIPS_REGSDEFS_H
+#ifndef __ASM_MIPS_REGDEF_H
+#define __ASM_MIPS_REGDEF_H
 
 /*
- * Symbolic register names
+ * Symbolic register names for 32 bit ABI
  */
 #define zero    $0      /* wired zero */
-#define AT      $1      /* assembler temp (uprcase, because ".set at") */
+#define AT      $1      /* assembler temp  - uppercase because of ".set at" */
 #define v0      $2      /* return value */
 #define v1      $3
 #define a0      $4      /* argument registers */
 #define s7      $23
 #define t8      $24     /* caller saved */
 #define t9      $25
+#define jp      $25     /* PIC jump register */
 #define k0      $26     /* kernel scratch */
 #define k1      $27
 #define gp      $28     /* global pointer */
 #define sp      $29     /* stack pointer */
 #define fp      $30     /* frame pointer */
+#define s8     $30     /* same like fp! */
 #define ra      $31     /* return address */
 
-#endif /* __ASM_MIPS_REGSDEFS_H */
+#endif /* __ASM_MIPS_REGDEF_H */
diff --git a/include/asm-mips/resource.h b/include/asm-mips/resource.h
new file mode 100644 (file)
index 0000000..a214aa2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Process resource limits
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_RESOURCE_H
+#define __ASM_MIPS_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+#define RLIMIT_CPU     0               /* CPU time in ms */
+#define RLIMIT_FSIZE   1               /* Maximum filesize */
+#define RLIMIT_DATA    2               /* max data size */
+#define RLIMIT_STACK   3               /* max stack size */
+#define RLIMIT_CORE    4               /* max core file size */
+#define RLIMIT_NOFILE  5               /* max number of open files */
+#define RLIMIT_VMEM    6               /* mapped memory */
+#define RLIMIT_AS      RLIMIT_VMEM
+#define RLIMIT_RSS     7               /* max resident set size */
+#define RLIMIT_NPROC   8               /* max number of processes */
+#define RLIMIT_MEMLOCK 9               /* max locked-in-memory address space*/
+
+#define RLIM_NLIMITS   10
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS                                   \
+{                                                      \
+       {LONG_MAX, LONG_MAX},                           \
+       {LONG_MAX, LONG_MAX},                           \
+       {LONG_MAX, LONG_MAX},                           \
+       {_STK_LIM, _STK_LIM},                           \
+       {       0, LONG_MAX},                           \
+       {NR_OPEN, NR_OPEN},                             \
+       {LONG_MAX, LONG_MAX},                           \
+       {LONG_MAX, LONG_MAX},                           \
+       {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},       \
+       { LONG_MAX, LONG_MAX },                         \
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_MIPS_RESOURCE_H */
index 82bab0eaaaa825b62b162d9e33ead78253e582df..cfbe5aceaa9e129c23e608179e9b245d05aef70e 100644 (file)
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
  *
+ * Note that the quad functions are only being used for the 64 bit kernel and
+ * therefore it isn't really important that they will be misscompiled for
+ * 32-bit kernels.
  */
 #ifndef __ASM_MIPS_SEGMENT_H
 #define __ASM_MIPS_SEGMENT_H
 
+#ifndef __LANGUAGE_ASSEMBLY__
 /*
- * Memory segments (32bit kernel mode addresses)
+ * For memcpy()
  */
-#define KUSEG                   0x00000000
-#define KSEG0                   0x80000000
-#define KSEG1                   0xa0000000
-#define KSEG2                   0xc0000000
-#define KSEG3                   0xe0000000
+#include <linux/string.h>
 
 /*
- * returns the kernel segment base of a given address
+ * This is a gcc optimization barrier, which essentially
+ * inserts a sequence point in the gcc RTL tree that gcc
+ * can't move code around. This is needed when we enter
+ * or exit a critical region (in this case around user-level
+ * accesses that may sleep, and we can't let gcc optimize
+ * global state around them).
  */
-#define KSEGX(a)                (a & 0xe0000000)
-
-#ifndef __ASSEMBLY__
+#define __gcc_barrier() __asm__ __volatile__("": : :"memory")
 
 /*
- * Beware: the xxx_fs_word functions work on 16bit words!
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
  */
-#define get_fs_byte(addr) get_user_byte((char *)(addr))
-static inline unsigned char get_user_byte(const char *addr)
-{
-       return *addr;
-}
+#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
+#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
 
-#define get_fs_word(addr) get_user_word((short *)(addr))
-static inline unsigned short get_user_word(const short *addr)
-{
-       return *addr;
-}
+/*
+ * This is a silly but good way to make sure that
+ * the __put_user function is indeed always optimized,
+ * and that we use the correct sizes..
+ */
+extern int bad_user_access_length(void);
 
-#define get_fs_long(addr) get_user_long((int *)(addr))
-static inline unsigned long get_user_long(const int *addr)
+/* I should make this use unaligned transfers etc.. */
+static inline void __put_user(unsigned long x, void * y, int size)
 {
-       return *addr;
+       __gcc_barrier();
+       switch (size) {
+               case 1:
+                       *(char *) y = x;
+                       break;
+               case 2:
+                       *(short *) y = x;
+                       break;
+               case 4:
+                       *(int *) y = x;
+                       break;
+               case 8:
+                       *(long *) y = x;
+                       break;
+               default:
+                       bad_user_access_length();
+       }
+       __gcc_barrier();
 }
 
-#define get_fs_dlong(addr) get_user_dlong((long long *)(addr))
-static inline unsigned long get_user_dlong(const long long *addr)
+/* I should make this use unaligned transfers etc.. */
+static inline unsigned long __get_user(const void * y, int size)
 {
-       return *addr;
+       unsigned long result;
+
+       __gcc_barrier();
+       switch (size) {
+               case 1:
+                       result = *(unsigned char *) y;
+                       break;
+               case 2:
+                       result = *(unsigned short *) y;
+                       break;
+               case 4:
+                       result = *(unsigned int *) y;
+                       break;
+               case 8:
+                       result = *(unsigned long *) y;
+                       break;
+               default:
+                       result = bad_user_access_length();
+                       break;
+       }
+       __gcc_barrier();
+
+       return result;
 }
 
-#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
-static inline void put_user_byte(char val,char *addr)
-{
-       *addr = val;
-}
+#define get_fs_byte(addr) get_user((unsigned char *)(addr))
+#define get_fs_word(addr) get_user((unsigned short *)(addr))
+#define get_fs_long(addr) get_user((unsigned int *)(addr))
+#define get_fs_quad(addr) get_user((unsigned long *)(addr))
 
-#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
-static inline void put_user_word(short val,short * addr)
-{
-       *addr = val;
-}
+#define put_fs_byte(x,addr) put_user((x),(char *)(addr))
+#define put_fs_word(x,addr) put_user((x),(short *)(addr))
+#define put_fs_long(x,addr) put_user((x),(int *)(addr))
+#define put_fs_quad(x,addr) put_user((x),(long *)(addr))
 
-#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
-static inline void put_user_long(unsigned long val,int * addr)
+static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
-       *addr = val;
+       __gcc_barrier();
+       memcpy(to, from, n);
+       __gcc_barrier();
 }
 
-#define put_fs_dlong(x,addr) put_user_dlong((x),(int *)(addr))
-static inline void put_user_dlong(unsigned long val,long long * addr)
+static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
 {
-       *addr = val;
+       __gcc_barrier();
+       memcpy(to, from, n);
+       __gcc_barrier();
 }
 
-#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n))
-
-#define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
-
 /*
  * For segmented architectures, these are used to specify which segment
  * to use for the above functions.
@@ -94,18 +132,57 @@ static inline void put_user_dlong(unsigned long val,long long * addr)
 
 static inline unsigned long get_fs(void)
 {
-       return 0;
+       return USER_DS;
 }
 
 static inline unsigned long get_ds(void)
 {
-       return 0;
+       return KERNEL_DS;
 }
 
 static inline void set_fs(unsigned long val)
 {
 }
 
-#endif /* !__ASSEMBLY__ */
+#endif /* !__LANGUAGE_ASSEMBLY__ */
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#define PHYSADDR(a)            (((unsigned long)(a)) & 0x1fffffff)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KSEG0ADDR(a)           ((((unsigned long)(a)) & 0x1fffffff) | KSEG0)
+#define KSEG1ADDR(a)           ((((unsigned long)(a)) & 0x1fffffff) | KSEG1)
+#define KSEG2ADDR(a)           ((((unsigned long)(a)) & 0x1fffffff) | KSEG2)
+#define KSEG3ADDR(a)           ((((unsigned long)(a)) & 0x1fffffff) | KSEG3)
+
+/*
+ * Memory segments (64bit kernel mode addresses)
+ */
+#define XKUSEG                  0x0000 0000 0000 0000
+#define XKSSEG                  0x4000 0000 0000 0000
+#define XKPHYS                  0x8000 0000 0000 0000
+#define XKSEG                   0xc000 0000 0000 0000
+#define CKSEG0                  0xffff ffff 8000 0000
+#define CKSEG1                  0xffff ffff a000 0000
+#define CKSSEG                  0xffff ffff c000 0000
+#define CKSEG3                  0xffff ffff e000 0000
 
 #endif /* __ASM_MIPS_SEGMENT_H */
diff --git a/include/asm-mips/shmparam.h b/include/asm-mips/shmparam.h
new file mode 100644 (file)
index 0000000..b2441c8
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __ASM_MIPS_SHMPARAM_H
+#define __ASM_MIPS_SHMPARAM_H
+
+/* address range for shared memory attaches if no address passed to shmat() */
+#define SHM_RANGE_START        0x50000000
+#define SHM_RANGE_END  0x60000000
+
+/*
+ * Format of a swap-entry for shared memory pages currently out in
+ * swap space (see also mm/swap.c).
+ *
+ * SWP_TYPE = SHM_SWP_TYPE
+ * SWP_OFFSET is used as follows:
+ *
+ *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
+ *  bits 7..21: index of page within shared memory segment (SHM_IDX)
+ *             (actually fewer bits get used since SHMMAX is so low)
+ */
+
+/*
+ * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
+ * there is a static array of size SHMMNI.
+ */
+#define _SHM_ID_BITS   7
+#define SHM_ID_MASK    ((1<<_SHM_ID_BITS)-1)
+
+#define SHM_IDX_SHIFT  (_SHM_ID_BITS)
+#define _SHM_IDX_BITS  15
+#define SHM_IDX_MASK   ((1<<_SHM_IDX_BITS)-1)
+
+/*
+ * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
+ * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
+ */
+
+#define SHMMAX 0x1000000               /* 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                         /* max shm system wide (pages) */ \
+       (1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
+/*
+ * This constant is very large but the ABI in it's wisdom says ...
+ */
+#define        SHMLBA 0x40000                  /* attach addr a multiple of this */
+#define SHMSEG SHMMNI                  /* max shared segs per process */
+
+#endif /* __ASM_MIPS_SHMPARAM_H */
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
new file mode 100644 (file)
index 0000000..083a508
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_MIPS_SIGCONTEXT_H
+#define __ASM_MIPS_SIGCONTEXT_H
+
+/*
+ * This struct isn't in the ABI, so we continue to use the old
+ * pre 1.3 definition.  Needs to be changed for 64 bit kernels,
+ * but it's 4am ...
+ */
+struct sigcontext_struct {
+       unsigned long          sc_at, sc_v0, sc_v1, sc_a0, sc_a1, sc_a2, sc_a3;
+       unsigned long   sc_t0, sc_t1, sc_t2, sc_t3, sc_t4, sc_t5, sc_t6, sc_t7;
+       unsigned long   sc_s0, sc_s1, sc_s2, sc_s3, sc_s4, sc_s5, sc_s6, sc_s7;
+       unsigned long   sc_t8, sc_t9,               sc_gp, sc_sp, sc_fp, sc_ra;
+
+       unsigned long   sc_epc;
+       unsigned long   sc_cause;
+
+       unsigned long   sc_oldmask;
+};
+
+#endif /* __ASM_MIPS_SIGCONTEXT_H */
index 51258b6d1ea1ff23c1787dab8cba4e48a34bf57b..50e6447a48d0e580a6e3bd9d8da14b701fcb9b7c 100644 (file)
 #ifndef __ASM_MIPS_SIGNAL_H
 #define __ASM_MIPS_SIGNAL_H
 
-struct sigcontext_struct {
-       unsigned long          sc_at, sc_v0, sc_v1, sc_a0, sc_a1, sc_a2, sc_a3;
-       unsigned long   sc_t0, sc_t1, sc_t2, sc_t3, sc_t4, sc_t5, sc_t6, sc_t7;
-       unsigned long   sc_s0, sc_s1, sc_s2, sc_s3, sc_s4, sc_s5, sc_s6, sc_s7;
-       unsigned long   sc_t8, sc_t9,               sc_gp, sc_sp, sc_fp, sc_ra;
+/*
+ * For now ...
+ */
+#include <linux/types.h>
+typedef __u64  sigset_t;
 
-       unsigned long   sc_epc;
-       unsigned long   sc_cause;
+#if 0
+/*
+ * This is what we should really use but the kernel can't handle
+ * a non-scalar type yet.  Since we use 64 signals only anyway we
+ * just use __u64 and pad another 64 bits in the kernel for now ...
+ */
+typedef struct {
+       unsigned int    sigbits[4];
+} sigset_t;
+#endif
 
-       unsigned long   oldmask;
+#define _NSIG          65
+#define NSIG           _NSIG
+
+/*
+ * For 1.3.0 Linux/MIPS changed the signal numbers to be compatible the ABI.
+ */
+#define SIGHUP          1      /* Hangup (POSIX).  */
+#define SIGINT          2      /* Interrupt (ANSI).  */
+#define SIGQUIT                 3      /* Quit (POSIX).  */
+#define SIGILL          4      /* Illegal instruction (ANSI).  */
+#define SIGTRAP                 5      /* Trace trap (POSIX).  */
+#define SIGIOT          6      /* IOT trap (4.2 BSD).  */
+#define SIGABRT                 SIGIOT /* Abort (ANSI).  */
+#define SIGEMT          7
+#define SIGFPE          8      /* Floating-point exception (ANSI).  */
+#define SIGKILL                 9      /* Kill, unblockable (POSIX).  */
+#define SIGBUS         10      /* BUS error (4.2 BSD).  */
+#define SIGSEGV                11      /* Segmentation violation (ANSI).  */
+#define SIGSYS         12
+#define SIGPIPE                13      /* Broken pipe (POSIX).  */
+#define SIGALRM                14      /* Alarm clock (POSIX).  */
+#define SIGTERM                15      /* Termination (ANSI).  */
+#define SIGUSR1                16      /* User-defined signal 1 (POSIX).  */
+#define SIGUSR2                17      /* User-defined signal 2 (POSIX).  */
+#define SIGCHLD                18      /* Child status has changed (POSIX).  */
+#define SIGCLD         SIGCHLD /* Same as SIGCHLD (System V).  */
+#define SIGPWR         19      /* Power failure restart (System V).  */
+#define SIGWINCH       20      /* Window size change (4.3 BSD, Sun).  */
+#define SIGURG         21      /* Urgent condition on socket (4.2 BSD).  */
+#define SIGIO          22      /* I/O now possible (4.2 BSD).  */
+#define SIGPOLL                SIGIO   /* Pollable event occured (System V).  */
+#define SIGSTOP                23      /* Stop, unblockable (POSIX).  */
+#define SIGTSTP                24      /* Keyboard stop (POSIX).  */
+#define SIGCONT                25      /* Continue (POSIX).  */
+#define SIGTTIN                26      /* Background read from tty (POSIX).  */
+#define SIGTTOU                27      /* Background write to tty (POSIX).  */
+#define SIGVTALRM      28      /* Virtual alarm clock (4.2 BSD).  */
+#define SIGPROF                29      /* Profiling alarm clock (4.2 BSD).  */
+#define SIGXCPU                30      /* CPU limit exceeded (4.2 BSD).  */
+#define SIGXFSZ                31      /* File size limit exceeded (4.2 BSD).  */
+
+/*
+ * 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
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_STACK       0x1
+#define SA_ONSTACK     SA_STACK
+#define SA_RESTART     0x4
+#define SA_NOCLDSTOP   0x20000
+/* Non ABI signals */
+#define SA_INTERRUPT   0x01000000
+#define SA_NOMASK      0x02000000
+#define SA_ONESHOT     0x04000000
+
+#ifdef __KERNEL__
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#endif
+
+#define SIG_BLOCK          1   /* for blocking signals */
+#define SIG_UNBLOCK        2   /* for unblocking signals */
+#define SIG_SETMASK        3   /* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+/* Fake signal functions */
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+struct sigaction {
+       unsigned int    sa_flags;
+       __sighandler_t  sa_handler;
+       sigset_t        sa_mask;
+       /*
+        * To keep the ABI structure size we have to fill a little gap ...
+        */
+       unsigned int    sa_mask_pad[2];
+
+       /* Abi says here follows reserved int[2] */
+       void            (*sa_restorer)(void);
+#if __mips < 3
+       /*
+        * For 32 bit code we have to pad struct sigaction to get
+        * constant size for the ABI
+        */
+       int             pad0[1];        /* reserved */
+#endif
 };
 
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+#endif
+
 #endif /* __ASM_MIPS_SIGNAL_H */
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
new file mode 100644 (file)
index 0000000..00779b1
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __ASM_MIPS_SOCKET_H
+#define __ASM_MIPS_SOCKET_H
+
+#include <linux/types.h>
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN      _IOR('f', 123, int)
+#define FIOSETOWN      _IOW('f', 124, int)
+
+#define SIOCATMARK     _IOR('s', 7, int)
+#define SIOCSPGRP      _IOW('s', 8, pid_t)
+#define SIOCGPGRP      _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP     0x8906                  /* Get stamp - linux-specific */
+
+/*
+ * For setsockoptions(2)
+ *
+ * This defines are ABI conformant as far as Linux supports these ...
+ */
+#define SOL_SOCKET     0xffff
+
+#define SO_DEBUG       0x0001
+#define SO_REUSEADDR   0x0004
+#define SO_KEEPALIVE   0x0008
+#define SO_DONTROUTE   0x0010
+#define SO_BROADCAST   0x0020
+#define SO_LINGER      0x0080
+#define SO_OOBINLINE   0x0100
+/* To add: #define SO_REUSEPORT 0x0200 */
+
+#define SO_TYPE                0x1008
+#define SO_ERROR       0x1007
+#define SO_SNDBUF      0x1001
+#define SO_RCVBUF      0x1002
+
+/* linux-specific, might as well be the same as on i386 */
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_BSDCOMPAT   14
+
+/*
+ * Wierd.  There are two ABIs; in the old one SOCK_STREAM and SOCK_DGRAM
+ * have swapped values.  I choose to be compatible with the new one.
+ */
+#define SOCK_DGRAM     1               /* datagram (conn.less) socket  */
+#define SOCK_STREAM    2               /* stream (connection) socket   */
+#define SOCK_RAW       3               /* raw socket                   */
+#define SOCK_RDM       4               /* reliably-delivered message   */
+#define SOCK_SEQPACKET 5               /* sequential packet socket     */
+#define SOCK_PACKET    10              /* linux specific way of        */
+                                       /* getting packets at the dev   */
+                                       /* level.  For writing rarp and */
+                                       /* other similar things on the  */
+                                       /* user level.                  */
+
+#endif /* __ASM_MIPS_SOCKET_H */
index 4c859c613277adca7ed189f2ffb57199732261f7..b3b69f3c64afca3a6d1482ad41f947dad59eee93 100644 (file)
 /*
  * Stack layout for all exceptions:
  *
- * ptrace needs to have all regs on the stack.
- * if the order here is changed, it needs to be 
- * updated in asm/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
- * asm-mips/ptrace.c, include/asm-mips/ptrace.h
- * and asm-mips/ptrace
- */
-
-/*
- * Offsets into the Interrupt stackframe.
- * The first 20 bytes are reserved for the usual MIPS calling sequence
+ * ptrace needs to have all regs on the stack. If the order here is changed,
+ * it needs to be updated in include/asm-mips/ptrace.h
+ *
+ * The first PTRSIZE*5 bytes are argument save space for C subroutines.
  */
-#define FR_REG1                20
+#define FR_REG1                (PTRSIZE*5)
 #define FR_REG2                ((FR_REG1) + 4)
 #define FR_REG3                ((FR_REG2) + 4)
 #define FR_REG4                ((FR_REG3) + 4)
  */
 #define FR_INTERRUPT   ((FR_CAUSE) + 4)
 #define FR_ORIG_REG2   ((FR_INTERRUPT) + 4)
+#define FR_PAD1                ((FR_ORIG_REG2) + 4)
 
 /*
- * Size of stack frame
+ * Size of stack frame, word/double word alignment
  */
-#define FR_SIZE                ((FR_ORIG_REG2) + 4)
+#define FR_SIZE                ((((FR_PAD1) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1))
 
-#define SAVE_ALL                                \
-               mfc0    k0,CP0_STATUS;          \
-               andi    k0,0x18;                /* extract KSU bits */ \
-               beqz    k0,1f;                  \
-               move    k1,sp;                  \
-               /*                              \
-                * Called from user mode, new stack \
-                */                             \
-               lui     k1,%hi(_kernelsp);      \
-               lw      k1,%lo(_kernelsp)(k1);  \
-1:             move    k0,sp;                  \
-               subu    sp,k1,FR_SIZE;          \
-               sw      k0,FR_REG29(sp);        \
-               sw      $2,FR_REG2(sp);         \
-               sw      $2,FR_ORIG_REG2(sp);    \
-               mfc0    v0,CP0_STATUS;          \
-               sw      v0,FR_STATUS(sp);       \
-               mfc0    v0,CP0_CAUSE;           \
-               sw      v0,FR_CAUSE(sp);        \
-               mfc0    v0,CP0_EPC;             \
-               sw      v0,FR_EPC(sp);          \
-               mfhi    v0;                     \
-               sw      v0,FR_HI(sp);           \
-               mflo    v0;                     \
-               sw      v0,FR_LO(sp);           \
-               sw      $1,FR_REG1(sp);         \
-               sw      $3,FR_REG3(sp);         \
-               sw      $4,FR_REG4(sp);         \
-               sw      $5,FR_REG5(sp);         \
-               sw      $6,FR_REG6(sp);         \
-               sw      $7,FR_REG7(sp);         \
-               sw      $8,FR_REG8(sp);         \
-               sw      $9,FR_REG9(sp);         \
-               sw      $10,FR_REG10(sp);       \
-               sw      $11,FR_REG11(sp);       \
-               sw      $12,FR_REG12(sp);       \
-               sw      $13,FR_REG13(sp);       \
-               sw      $14,FR_REG14(sp);       \
-               sw      $15,FR_REG15(sp);       \
-               sw      $16,FR_REG16(sp);       \
-               sw      $17,FR_REG17(sp);       \
-               sw      $18,FR_REG18(sp);       \
-               sw      $19,FR_REG19(sp);       \
-               sw      $20,FR_REG20(sp);       \
-               sw      $21,FR_REG21(sp);       \
-               sw      $22,FR_REG22(sp);       \
-               sw      $23,FR_REG23(sp);       \
-               sw      $24,FR_REG24(sp);       \
-               sw      $25,FR_REG25(sp);       \
-               sw      $28,FR_REG28(sp);       \
-               sw      $30,FR_REG30(sp);       \
-               sw      $31,FR_REG31(sp)
+#ifdef __R4000__
 
-#define RESTORE_ALL                             \
-               lw      v1,FR_EPC(sp);          \
-               lw      v0,FR_HI(sp);           \
-               mtc0    v1,CP0_EPC;             \
-               lw      v1,FR_LO(sp);           \
-               mthi    v0;                     \
-               lw      v0,FR_STATUS(sp);       \
-               mtlo    v1;                     \
-               mtc0    v0,CP0_STATUS;          \
-               lw      $31,FR_REG31(sp);       \
-               lw      $30,FR_REG30(sp);       \
-               lw      $28,FR_REG28(sp);       \
-               lw      $25,FR_REG25(sp);       \
-               lw      $24,FR_REG24(sp);       \
-               lw      $23,FR_REG23(sp);       \
-               lw      $22,FR_REG22(sp);       \
-               lw      $21,FR_REG21(sp);       \
-               lw      $20,FR_REG20(sp);       \
-               lw      $19,FR_REG19(sp);       \
-               lw      $18,FR_REG18(sp);       \
-               lw      $17,FR_REG17(sp);       \
-               lw      $16,FR_REG16(sp);       \
-               lw      $15,FR_REG15(sp);       \
-               lw      $14,FR_REG14(sp);       \
-               lw      $13,FR_REG13(sp);       \
-               lw      $12,FR_REG12(sp);       \
-               lw      $11,FR_REG11(sp);       \
-               lw      $10,FR_REG10(sp);       \
-               lw      $9,FR_REG9(sp);         \
-               lw      $8,FR_REG8(sp);         \
-               lw      $7,FR_REG7(sp);         \
-               lw      $6,FR_REG6(sp);         \
-               lw      $5,FR_REG5(sp);         \
-               lw      $4,FR_REG4(sp);         \
-               lw      $3,FR_REG3(sp);         \
-               lw      $2,FR_REG2(sp);         \
-               lw      $1,FR_REG1(sp);         \
-               lw      sp,FR_REG29(sp); /* Deallocate stack */ \
-               eret
+#define SAVE_ALL                                        \
+               mfc0    k0,CP0_STATUS;                  \
+               sll     k0,3;     /* extract cu0 bit */ \
+               bltz    k0,8f;                          \
+               move    k1,sp;                          \
+               /*                                      \
+                * Called from user mode, new stack     \
+                */                                     \
+               lui     k1,%hi(kernelsp);               \
+               lw      k1,%lo(kernelsp)(k1);           \
+8:             move    k0,sp;                          \
+               subu    sp,k1,FR_SIZE;                  \
+               sw      k0,FR_REG29(sp);                \
+               sw      $2,FR_REG2(sp);                 \
+               sw      $2,FR_ORIG_REG2(sp);            \
+               mfc0    v0,CP0_STATUS;                  \
+               sw      v0,FR_STATUS(sp);               \
+               mfc0    v0,CP0_CAUSE;                   \
+               sw      v0,FR_CAUSE(sp);                \
+               mfc0    v0,CP0_EPC;                     \
+               sw      v0,FR_EPC(sp);                  \
+               mfhi    v0;                             \
+               sw      v0,FR_HI(sp);                   \
+               mflo    v0;                             \
+               sw      v0,FR_LO(sp);                   \
+               sw      $1,FR_REG1(sp);                 \
+               sw      $3,FR_REG3(sp);                 \
+               sw      $4,FR_REG4(sp);                 \
+               sw      $5,FR_REG5(sp);                 \
+               sw      $6,FR_REG6(sp);                 \
+               sw      $7,FR_REG7(sp);                 \
+               sw      $8,FR_REG8(sp);                 \
+               sw      $9,FR_REG9(sp);                 \
+               sw      $10,FR_REG10(sp);               \
+               sw      $11,FR_REG11(sp);               \
+               sw      $12,FR_REG12(sp);               \
+               sw      $13,FR_REG13(sp);               \
+               sw      $14,FR_REG14(sp);               \
+               sw      $15,FR_REG15(sp);               \
+               sw      $16,FR_REG16(sp);               \
+               sw      $17,FR_REG17(sp);               \
+               sw      $18,FR_REG18(sp);               \
+               sw      $19,FR_REG19(sp);               \
+               sw      $20,FR_REG20(sp);               \
+               sw      $21,FR_REG21(sp);               \
+               sw      $22,FR_REG22(sp);               \
+               sw      $23,FR_REG23(sp);               \
+               sw      $24,FR_REG24(sp);               \
+               sw      $25,FR_REG25(sp);               \
+               sw      $28,FR_REG28(sp);               \
+               sw      $30,FR_REG30(sp);               \
+               sw      $31,FR_REG31(sp)
 
 /*
- * Move to kernel mode and disable interrupts
+ * Note that we restore the IE flags from stack. This means
+ * that a modified IE mask will be nullified.
  */
-#define CLI                                     \
-               mfc0    k0,CP0_STATUS;          \
-               ori     k0,k0,0x1f;             \
-               xori    k0,k0,0x1f;             \
-               mtc0    k0,CP0_STATUS
+#define RESTORE_ALL                                     \
+               .set    mips3;                          \
+               mfc0    t0,CP0_STATUS;                  \
+               ori     t0,0x1f;                        \
+               xori    t0,0x1f;                        \
+               mtc0    t0,CP0_STATUS;                  \
+               \
+               lw      v0,FR_STATUS(sp);               \
+               lw      v1,FR_LO(sp);                   \
+               mtc0    v0,CP0_STATUS;                  \
+               mtlo    v1;                             \
+               lw      v0,FR_HI(sp);                   \
+               lw      v1,FR_EPC(sp);                  \
+               mthi    v0;                             \
+               mtc0    v1,CP0_EPC;                     \
+               lw      $31,FR_REG31(sp);               \
+               lw      $30,FR_REG30(sp);               \
+               lw      $28,FR_REG28(sp);               \
+               lw      $25,FR_REG25(sp);               \
+               lw      $24,FR_REG24(sp);               \
+               lw      $23,FR_REG23(sp);               \
+               lw      $22,FR_REG22(sp);               \
+               lw      $21,FR_REG21(sp);               \
+               lw      $20,FR_REG20(sp);               \
+               lw      $19,FR_REG19(sp);               \
+               lw      $18,FR_REG18(sp);               \
+               lw      $17,FR_REG17(sp);               \
+               lw      $16,FR_REG16(sp);               \
+               lw      $15,FR_REG15(sp);               \
+               lw      $14,FR_REG14(sp);               \
+               lw      $13,FR_REG13(sp);               \
+               lw      $12,FR_REG12(sp);               \
+               lw      $11,FR_REG11(sp);               \
+               lw      $10,FR_REG10(sp);               \
+               lw      $9,FR_REG9(sp);                 \
+               lw      $8,FR_REG8(sp);                 \
+               lw      $7,FR_REG7(sp);                 \
+               lw      $6,FR_REG6(sp);                 \
+               lw      $5,FR_REG5(sp);                 \
+               lw      $4,FR_REG4(sp);                 \
+               lw      $3,FR_REG3(sp);                 \
+               lw      $2,FR_REG2(sp);                 \
+               lw      $1,FR_REG1(sp);                 \
+               lw      sp,FR_REG29(sp); /* Deallocate stack */ \
+               .set    mips0
 
-/*
- * Move to kernel mode and enable interrupts
- */
-#define STI                                     \
-               mfc0    k0,CP0_STATUS;          \
-               ori     k0,k0,0x1f;             \
-               xori    k0,k0,0x1e;             \
-               mtc0    k0,CP0_STATUS
+#else /* !defined (__R4000__) */
+
+#error "Implement SAVE_ALL and RESTORE_ALL!"
+
+#endif /* !defined (__R4000__) */
 
 #endif /* __ASM_MIPS_STACKFRAME_H */
diff --git a/include/asm-mips/stat.h b/include/asm-mips/stat.h
new file mode 100644 (file)
index 0000000..0281bc1
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __ASM_MIPS_STAT_H
+#define __ASM_MIPS_STAT_H
+
+#include <linux/types.h>
+
+struct old_stat {
+       unsigned int    st_dev;
+       unsigned int    st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_rdev;
+       long            st_size;
+       unsigned int    st_atime, st_res1;
+       unsigned int    st_mtime, st_res2;
+       unsigned int    st_ctime, st_res3;
+       unsigned int    st_blkize;
+       int             st_blocks;
+       unsigned int    st_flags;
+       unsigned int    st_gen;
+};
+
+struct new_stat {
+       dev_t           st_dev;
+       long            st_pad1[3];             /* Reserved for network id */
+       ino_t           st_ino;
+       mode_t          st_mode;
+       nlink_t         st_nlink;
+       uid_t           st_uid;
+       gid_t           st_gid;
+       dev_t           st_rdev;
+       long            st_pad2[2];
+       off_t           st_size;
+       long            st_pad3;
+       /*
+        * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+        * but we don't have it under Linux.
+        */
+       time_t          st_atime;
+       long            reserved0;
+       time_t          st_mtime;
+       long            reserved1;
+       time_t          st_ctime;
+       long            reserved2;
+       long            st_blksize;
+       long            st_blocks;
+       char            st_fstype[16];  /* Filesystem type name */
+       long            st_pad4[8];
+       /* Linux specific fields */
+       unsigned int    st_flags;
+       unsigned int    st_gen;
+};
+
+#endif /* __ASM_MIPS_STAT_H */
diff --git a/include/asm-mips/statfs.h b/include/asm-mips/statfs.h
new file mode 100644 (file)
index 0000000..3cae732
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_MIPS_STATFS_H
+#define __ASM_MIPS_STATFS_H
+
+typedef struct {
+       long    val[2];
+} fsid_t;
+
+struct statfs {
+       long    f_type;
+#define f_fstyp f_type
+       long    f_bsize;
+       long    f_frsize;       /* Fragment size - unsupported */
+       long    f_blocks;
+       long    f_bfree;
+       long    f_files;
+       long    f_ffree;
+
+       /* Linux specials */
+       long    f_bavail;
+       fsid_t  f_fsid;
+       long    f_namelen;
+       long    f_spare[6];
+};
+
+#endif /* __ASM_MIPS_STATFS_H */
index 93313f6ae17ba26f2cc1fdf8ff433e160ef3c576..ce0ae940ec220d048f42afc86b8278884ca3f280 100644 (file)
@@ -8,12 +8,10 @@
  * Copyright (c) 1994, 1995  Waldorf Electronics
  * written by Ralf Baechle
  */
-
 #ifndef __ASM_MIPS_STRING_H
 #define __ASM_MIPS_STRING_H
 
-#include <asm/mipsregs.h>
-
+#define __HAVE_ARCH_STRCPY
 extern __inline__ char * strcpy(char * dest, const char *src)
 {
   char *xdest = dest;
@@ -22,10 +20,10 @@ extern __inline__ char * strcpy(char * dest, const char *src)
        ".set\tnoreorder\n\t"
        ".set\tnoat\n"
        "1:\tlbu\t$1,(%1)\n\t"
-       "addiu\t%1,%1,1\n\t"
+       "addiu\t%1,1\n\t"
        "sb\t$1,(%0)\n\t"
        "bnez\t$1,1b\n\t"
-       "addiu\t%0,%0,1\n\t"
+       "addiu\t%0,1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
        : "=r" (dest), "=r" (src)
@@ -35,6 +33,7 @@ extern __inline__ char * strcpy(char * dest, const char *src)
   return xdest;
 }
 
+#define __HAVE_ARCH_STRNCPY
 extern __inline__ char * strncpy(char *dest, const char *src, size_t n)
 {
   char *xdest = dest;
@@ -62,6 +61,7 @@ extern __inline__ char * strncpy(char *dest, const char *src, size_t n)
   return dest;
 }
 
+#define __HAVE_ARCH_STRCMP
 extern __inline__ int strcmp(const char * cs, const char * ct)
 {
   int __res;
@@ -71,16 +71,18 @@ extern __inline__ int strcmp(const char * cs, const char * ct)
        ".set\tnoat\n\t"
        "lbu\t%2,(%0)\n"
        "1:\tlbu\t$1,(%1)\n\t"
-       "addiu\t%0,%0,1\n\t"
+       "addiu\t%0,1\n\t"
        "bne\t$1,%2,2f\n\t"
-       "addiu\t%1,%1,1\n\t"
+       "addiu\t%1,1\n\t"
        "bnez\t%2,1b\n\t"
        "lbu\t%2,(%0)\n\t"
-       STR(FILL_LDS) "\n\t"
+#ifndef __R4000__
+       "nop\n\t"
+#endif
        "move\t%2,$1\n"
-       "2:\tsub\t%2,%2,$1\n"
+       "2:\tsubu\t%2,$1\n"
        "3:\t.set\tat\n\t"
-       ".set\treorder\n\t"
+       ".set\treorder"
        : "=d" (cs), "=d" (ct), "=d" (__res)
        : "0" (cs), "1" (ct)
        : "$1");
@@ -88,6 +90,7 @@ extern __inline__ int strcmp(const char * cs, const char * ct)
   return __res;
 }
 
+#define __HAVE_ARCH_STRNCMP
 extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
 {
   char __res;
@@ -98,13 +101,13 @@ extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
                "1:\tlbu\t%3,(%0)\n\t"
        "beqz\t%2,2f\n\t"
         "lbu\t$1,(%1)\n\t"
-               "addiu\t%2,%2,-1\n\t"
+               "subu\t%2,1\n\t"
         "bne\t$1,%3,3f\n\t"
-        "addiu\t%0,%0,1\n\t"
+        "addiu\t%0,1\n\t"
         "bnez\t%3,1b\n\t"
-        "addiu\t%1,%1,1\n"
+        "addiu\t%1,1\n"
        "2:\tmove\t%3,$1\n"
-       "3:\tsub\t%3,%3,$1\n\t"
+       "3:\tsubu\t%3,$1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
         : "=d" (cs), "=d" (ct), "=d" (count), "=d" (__res)
@@ -114,6 +117,7 @@ extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
   return __res;
 }
 
+#define __HAVE_ARCH_MEMSET
 extern __inline__ void * memset(void * s, int c, size_t count)
 {
   void *xs = s;
@@ -133,6 +137,7 @@ extern __inline__ void * memset(void * s, int c, size_t count)
   return xs;
 }
 
+#define __HAVE_ARCH_MEMCPY
 extern __inline__ void * memcpy(void * to, const void * from, size_t n)
 {
   void *xto = to;
@@ -143,11 +148,11 @@ extern __inline__ void * memcpy(void * to, const void * from, size_t n)
        ".set\tnoreorder\n\t"
        ".set\tnoat\n"
        "1:\tlbu\t$1,(%1)\n\t"
-       "addiu\t%1,%1,1\n\t"
+       "addiu\t%1,1\n\t"
        "sb\t$1,(%0)\n\t"
-       "subu\t%2,%2,1\n\t"
+       "subu\t%2,1\n\t"
        "bnez\t%2,1b\n\t"
-       "addiu\t%0,%0,1\n\t"
+       "addiu\t%0,1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
         : "=r" (to), "=r" (from), "=r" (n)
@@ -156,6 +161,7 @@ extern __inline__ void * memcpy(void * to, const void * from, size_t n)
   return xto;
 }
 
+#define __HAVE_ARCH_MEMMOVE
 extern __inline__ void * memmove(void * dest,const void * src, size_t n)
 {
   void *xdest = dest;
@@ -168,11 +174,11 @@ extern __inline__ void * memmove(void * dest,const void * src, size_t n)
        ".set\tnoreorder\n\t"
        ".set\tnoat\n"
        "1:\tlbu\t$1,(%1)\n\t"
-       "addiu\t%1,%1,1\n\t"
+       "addiu\t%1,1\n\t"
        "sb\t$1,(%0)\n\t"
-       "subu\t%2,%2,1\n\t"
+       "subu\t%2,1\n\t"
        "bnez\t%2,1b\n\t"
-       "addiu\t%0,%0,1\n\t"
+       "addiu\t%0,1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
         : "=r" (dest), "=r" (src), "=r" (n)
@@ -183,11 +189,11 @@ extern __inline__ void * memmove(void * dest,const void * src, size_t n)
        ".set\tnoreorder\n\t"
        ".set\tnoat\n"
        "1:\tlbu\t$1,-1(%1)\n\t"
-       "subu\t%1,%1,1\n\t"
+       "subu\t%1,1\n\t"
        "sb\t$1,-1(%0)\n\t"
-       "subu\t%2,%2,1\n\t"
+       "subu\t%2,1\n\t"
        "bnez\t%2,1b\n\t"
-       "subu\t%0,%0,1\n\t"
+       "subu\t%0,1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
         : "=r" (dest), "=r" (src), "=r" (n)
@@ -196,17 +202,18 @@ extern __inline__ void * memmove(void * dest,const void * src, size_t n)
   return xdest;
 }
 
+#define __HAVE_ARCH_MEMSCAN
 extern __inline__ void * memscan(void * addr, int c, size_t size)
 {
        if (!size)
                return addr;
        __asm__(".set\tnoreorder\n\t"
                ".set\tnoat\n"
-               "1:\tbeq\t$0,%1,2f\n\t"
+               "1:\tbeqz\t%1,2f\n\t"
                "lbu\t$1,(%0)\n\t"
-               "subu\t%1,%1,1\n\t"
+               "subu\t%1,1\n\t"
                "bnez\t%1,1b\n\t"
-               "addiu\t%0,%0,1\n\t"
+               "addiu\t%0,1\n\t"
                ".set\tat\n\t"
                ".set\treorder\n"
                "2:"
diff --git a/include/asm-mips/sysmips.h b/include/asm-mips/sysmips.h
new file mode 100644 (file)
index 0000000..3c29055
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Definitions for the MIPS sysmips(2) call
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SYSMIPS_H
+#define __ASM_MIPS_SYSMIPS_H
+
+/*
+ * Commands for the sysmips(2) call
+ *
+ * sysmips(2) is deprecated - though some existing software uses it.
+ * We only support the following commands.
+ */
+#define SETNAME                    1   /* set hostname                  */
+#define FLUSH_CACHE               3    /* writeback and invalide caches */
+#define MIPS_FIXADE                7   /* control address error fixing  */
+#define MIPS_ATOMIC_SET                2001    /* atomically set variable       */
+
+#endif /* __ASM_MIPS_SYSMIPS_H */
index c3355109523dd6d1ceff37a04731586ed224daaa..353acf6ac6dd3869bdd4d591b841e344dfb60ee4 100644 (file)
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
-
 #ifndef __ASM_MIPS_SYSTEM_H
 #define __ASM_MIPS_SYSTEM_H
 
-#include <linux/types.h>
-#include <asm/segment.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
+#include <linux/kernel.h>
 
-/*
- * (Currently empty to support debugging)
- */
-#define move_to_user_mode()              \
-__asm__ __volatile__ (                   \
+#if defined (__R4000__)
+#define sti()                            \
+__asm__ __volatile__(                    \
        ".set\tnoreorder\n\t"            \
        ".set\tnoat\n\t"                 \
-       "la\t$1,1f\n\t"                  \
-       "subu\t$1,$1,%0\n\t"             \
-       "jr\t$1\n\t"                     \
        "mfc0\t$1,$12\n\t"               \
-       "1:ori\t$1,0x00\n\t"             \
+       "ori\t$1,0x1f\n\t"               \
+       "xori\t$1,0x1e\n\t"              \
        "mtc0\t$1,$12\n\t"               \
-       "subu\t$29,%0\n\t"               \
        ".set\tat\n\t"                   \
        ".set\treorder"                  \
        : /* no outputs */               \
-       : "r" (KERNELBASE));
+       : /* no inputs */                \
+       : "$1")
 
-#if defined (__R4000__)
-#define sti() \
+#define cli()                            \
 __asm__ __volatile__(                    \
+       ".set\tnoreorder\n\t"            \
        ".set\tnoat\n\t"                 \
-       "mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
-       "ori\t$1,$1,0x1f\n\t"            \
-       "xori\t$1,$1,0x1e\n\t"           \
-       "mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
-       ".set\tat"                       \
+       "mfc0\t$1,$12\n\t"               \
+       "ori\t$1,1\n\t"                  \
+       "xori\t$1,1\n\t"                 \
+       "mtc0\t$1,$12\n\t"               \
+       "nop\n\t"                        \
+       "nop\n\t"                        \
+       "nop\n\t"                        \
+       ".set\tat\n\t"                   \
+       ".set\treorder"                  \
        : /* no outputs */               \
        : /* no inputs */                \
        : "$1")
 
-#define cli() \
+#else /* !defined (__R4000__) */
+/*
+ * Untested goodies for the R3000 based DECstation et al.
+ */
+#define sti()                            \
 __asm__ __volatile__(                    \
+       ".set\tnoreorder\n\t"            \
        ".set\tnoat\n\t"                 \
-       "mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
-       "ori\t$1,$1,1\n\t"               \
-       "xori\t$1,$1,1\n\t"              \
-       "mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
-       ".set\tat"                       \
+       "mfc0\t$1,$12\n\t"               \
+       "ori\t$1,0x01\n\t"               \
+       "mtc0\t$1,$12\n\t"               \
+       ".set\tat\n\t"                   \
+       ".set\treorder"                  \
+       : /* no outputs */               \
+       : /* no inputs */                \
+       : "$1")
+
+#define cli()                            \
+__asm__ __volatile__(                    \
+       ".set\tnoreorder\n\t"            \
+       ".set\tnoat\n\t"                 \
+       "mfc0\t$1,$12\n\t"               \
+       "ori\t$1,1\n\t"                  \
+       "xori\t$1,1\n\t"                 \
+       "mtc0\t$1,$12\n\t"               \
+       ".set\tat\n\t"                   \
+       ".set\treorder"                  \
        : /* no outputs */               \
        : /* no inputs */                \
        : "$1")
-#else /* !defined (__R4000__) */
-/*
- * Cheese - I don't have a R3000 manual
- */
-#error "Yikes - write cli()/sti() macros for  R3000!"
 #endif /* !defined (__R4000__) */
 
 #define nop() __asm__ __volatile__ ("nop")
 
 #define save_flags(x)                    \
 __asm__ __volatile__(                    \
-       "mfc0\t%0,$12"                   \
+       ".set\tnoreorder\n\t"            \
+       "mfc0\t%0,$12\n\t"               \
+       ".set\treorder"                  \
        : "=r" (x))                      \
 
 #define restore_flags(x)                 \
 __asm__ __volatile__(                    \
-       "mtc0\t%0,$12"                   \
+       ".set\tnoreorder\n\t"            \
+       "mtc0\t%0,$12\n\t"               \
+       "nop\n\t"                        \
+       "nop\n\t"                        \
+       "nop\n\t"                        \
+       ".set\treorder"                  \
        : /* no output */                \
        : "r" (x))                       \
 
-extern inline unsigned long xchg_u8(char * m, unsigned long val)
+#define sync_mem()                       \
+__asm__ __volatile__(                    \
+       ".set\tnoreorder\n\t"            \
+       "sync\n\t"                       \
+       ".set\treorder")                 \
+
+/*
+ * The 8 and 16 bit variants have to disable interrupts temporarily.
+ * Both are currently unused.
+ */
+extern inline unsigned long xchg_u8(volatile char * m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -92,7 +119,7 @@ extern inline unsigned long xchg_u8(char * m, unsigned long val)
        return retval;
 }
 
-extern inline unsigned long xchg_u16(short * m, unsigned long val)
+extern inline unsigned long xchg_u16(volatile short * m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -107,9 +134,9 @@ extern inline unsigned long xchg_u16(short * m, unsigned long val)
 
 /*
  * For 32 and 64 bit operands we can take advantage of ll and sc.
- * The later isn't currently being used.
+ * FIXME: This doesn't work for R3000 machines.
  */
-extern inline unsigned long xchg_u32(int * m, unsigned long val)
+extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
        unsigned long dummy;
 
@@ -119,17 +146,20 @@ extern inline unsigned long xchg_u32(int * m, unsigned long val)
                "ll\t%0,(%1)\n"
                "1:\tmove\t$1,%2\n\t"
                "sc\t$1,(%1)\n\t"
-               "beqzl\t%3,1b\n\t"
+               "beqzl\t$1,1b\n\t"
                "ll\t%0,(%1)\n\t"
                ".set\tat\n\t"
                ".set\treorder"
                : "=r" (val), "=r" (m), "=r" (dummy)
-               : "1" (*m), "2" (val));
+               : "1" (m), "2" (val));
 
        return val;
 }
 
-extern inline unsigned long xchg_u64(long * m, unsigned long val)
+/*
+ * Only used for 64 bit kernel.
+ */
+extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
 {
        unsigned long dummy;
 
@@ -139,65 +169,52 @@ extern inline unsigned long xchg_u64(long * m, unsigned long val)
                "lld\t%0,(%1)\n"
                "1:\tmove\t$1,%2\n\t"
                "scd\t$1,(%1)\n\t"
-               "beqzl\t%3,1b\n\t"
+               "beqzl\t$1,1b\n\t"
                "ll\t%0,(%1)\n\t"
                ".set\tat\n\t"
                ".set\treorder"
                : "=r" (val), "=r" (m), "=r" (dummy)
-               : "1" (*m), "2" (val));
+               : "1" (m), "2" (val));
 
        return val;
 }
 
-#if 0
-extern inline int tas(char * m)
-{
-       return xchg_u8(m,1);
-}
-#endif
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid xchg().
+ *
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+extern void __xchg_called_with_bad_pointer(void);
 
-extern inline void * xchg_ptr(void * m, void * val)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
-       return (void *) xchg_u32(m, (unsigned long) val);
+       switch (size) {
+               case 1:
+                       return xchg_u8(ptr, x);
+               case 2:
+                       return xchg_u16(ptr, x);
+               case 4:
+                       return xchg_u32(ptr, x);
+               case 8:
+                       return xchg_u64(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
 }
 
-extern ulong IRQ_vectors[256];
-extern ulong exception_handlers[256];
+extern unsigned long IRQ_vectors[16];
+extern unsigned long exception_handlers[32];
 
-#define set_intr_gate(n,addr) \
-       IRQ_vectors[n] = (ulong) (addr)
+#define set_int_vector(n,addr) \
+       IRQ_vectors[n] = (unsigned long) (addr)
 
 #define set_except_vector(n,addr) \
-       exception_handlers[n] = (ulong) (addr)
-
-/*
- * atomic exchange of one word
- */
-#if defined (__R4000__)
-#define atomic_exchange(m,r)             \
-       __asm__ __volatile__(            \
-               ".set\tnoreorder\n\t"    \
-               "ll\t%0,(%2)\n"          \
-               "1:\tmove\t$8,%1\n\t"    \
-               "sc\t$8,(%2)\n\t"        \
-               "beql\t$0,$8,1b\n\t"     \
-               "ll\t%0,(%2)\n\t"        \
-               ".set\treorder"          \
-               : "=r" (r)               \
-               : "r" (r), "r" (&(m))    \
-               : "$8","memory")
-#else
-#define atomic_exchange(m,r)             \
-       {                                \
-               unsigned long flags;     \
-               unsigned long tmp;       \
-               save_flags(flags);       \      
-               cli();                   \
-               tmp = (m);               \
-               (m) = (r);               \
-               (r) = tmp;               \
-               restore_flags(flags);    \      
-       }
-#endif
+       exception_handlers[n] = (unsigned long) (addr)
 
 #endif /* __ASM_MIPS_SYSTEM_H */
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
new file mode 100644 (file)
index 0000000..60858b1
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __ASM_MIPS_TERMBITS_H
+#define __ASM_MIPS_TERMBITS_H
+
+#include <asm/ioctl.h>
+#include <asm/ioctls.h>
+
+/*
+ * The ABI says nothing about NCC but seems to use NCCS as
+ * replacement for it in struct termio
+ */
+#define NCC    8
+#define NCCS   23
+
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       char c_line;                    /* line discipline */
+       unsigned char c_cc[NCCS];       /* control characters */
+};
+
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       /*
+        * Seems nonexistant in the ABI, but Linux assumes existence ...
+        */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+};
+
+#endif /* __ASM_MIPS_TERMBITS_H */
diff --git a/include/asm-mips/termios.h b/include/asm-mips/termios.h
new file mode 100644 (file)
index 0000000..893b98f
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __ASM_MIPS_TERMIOS_H
+#define __ASM_MIPS_TERMIOS_H
+
+#include <linux/types.h>
+#include <asm/termbits.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef __KERNEL__
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+extern inline void trans_from_termio(struct termio * termio,
+       struct termios * termios)
+{
+#define SET_LOW_BITS(x,y)      ((x) = (0xffff0000 & (x)) | (y))
+       SET_LOW_BITS(termios->c_iflag, termio->c_iflag);
+       SET_LOW_BITS(termios->c_oflag, termio->c_oflag);
+       SET_LOW_BITS(termios->c_cflag, termio->c_cflag);
+       SET_LOW_BITS(termios->c_lflag, termio->c_lflag);
+#undef SET_LOW_BITS
+       memcpy(termios->c_cc, termio->c_cc, NCC);
+}
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+extern inline void trans_to_termio(struct termios * termios,
+       struct termio * termio)
+{
+       termio->c_iflag = termios->c_iflag;
+       termio->c_oflag = termios->c_oflag;
+       termio->c_cflag = termios->c_cflag;
+       termio->c_lflag = termios->c_lflag;
+       termio->c_line  = termios->c_line;
+       memcpy(termio->c_cc, termios->c_cc, NCC);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_MIPS_TERMIOS_H */
index d791378e41c2f864bfd710e03e88f407cb04d373..30bb1904f82ca40b0beb7bf02c0cfd0235923946 100644 (file)
@@ -1,19 +1,39 @@
+/*
+ * include/asm-mips/types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf GMBH
+ * written by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TYPES_H
 #define __ASM_MIPS_TYPES_H
 
 #ifndef _SIZE_T
 #define _SIZE_T
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
 #endif
 
 #ifndef _SSIZE_T
 #define _SSIZE_T
-typedef long ssize_t;
+typedef __SSIZE_TYPE__ ssize_t;
 #endif
 
 #ifndef _PTRDIFF_T
 #define _PTRDIFF_T
-typedef long ptrdiff_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef long time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;
 #endif
 
 /*
@@ -55,8 +75,8 @@ typedef unsigned char u8;
 typedef __signed short s16;
 typedef unsigned short u16;
 
-typedef __signed long s32;
-typedef unsigned long u32;
+typedef __signed int s32;
+typedef unsigned int u32;
 
 #if ((~0UL) == 0xffffffff)
 
@@ -74,20 +94,65 @@ typedef unsigned long u64;
 
 #endif /* __KERNEL__ */
 
+typedef __s32 pid_t;
+typedef __s32 uid_t;
+typedef __s32 gid_t;
+typedef __u32 dev_t;
+typedef __u32 ino_t;
+typedef __u32 mode_t;
+typedef __u32 umode_t;
+typedef __u32 nlink_t;
+typedef long daddr_t;
+typedef long off_t;
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
+{
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
+{
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
+{ 
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
 /*
- * These definitions double the definitions from <gnu/types.h>.
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
  */
-#undef  __FDELT
-#define __FDELT(d)      ((d) / __NFDBITS)
-#undef  __FDMASK
-#define __FDMASK(d)     (1 << ((d) % __NFDBITS))
-#undef  __FD_SET
-#define __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#undef  __FD_CLR
-#define __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#undef  __FD_ISSET
-#define __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
-#undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(fd_set *p)
+{
+       unsigned int *tmp = p->fds_bits;
+       int i;
+
+       if (__builtin_constant_p(__FDSET_INTS)) {
+               switch (__FDSET_INTS) {
+                       case 8:
+                               tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+                               tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+                               return;
+               }
+       }
+       i = __FDSET_INTS;
+       while (i) {
+               i--;
+               *tmp = 0;
+               tmp++;
+       }
+}
 
 #endif /* __ASM_MIPS_TYPES_H */
index 38e568737c5f4a5174bb0e502d0514768ea9d701..b17f8e2153a36630d432178225bfe96a410a4422 100644 (file)
+/*
+ * This file contains the system call numbers.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_UNISTD_H
 #define __ASM_MIPS_UNISTD_H
 
-#ifdef __KERNEL__
+/*
+ * The syscalls 0 - 3999 are reserved for a down to the root syscall
+ * compatibility with Risc/OS and IRIX.  None of these syscalls has yet been
+ * implemented.  We'll see how to deal with the various "real" BSD variants
+ * like Ultrix, NetBSD ...
+ */
+
+/*
+ * SVR4 syscalls are in the range from 1 to 999
+ */
+#define __NR_SVR4                      0
+#define __NR_SVR4_syscall              (__NR_SVR4 +   0)
+#define __NR_SVR4_exit                 (__NR_SVR4 +   1)
+#define __NR_SVR4_fork                 (__NR_SVR4 +   2)
+#define __NR_SVR4_read                 (__NR_SVR4 +   3)
+#define __NR_SVR4_write                        (__NR_SVR4 +   4)
+#define __NR_SVR4_open                 (__NR_SVR4 +   5)
+#define __NR_SVR4_close                        (__NR_SVR4 +   6)
+#define __NR_SVR4_wait                 (__NR_SVR4 +   7)
+#define __NR_SVR4_creat                        (__NR_SVR4 +   8)
+#define __NR_SVR4_link                 (__NR_SVR4 +   9)
+#define __NR_SVR4_unlink               (__NR_SVR4 +  10)
+#define __NR_SVR4_exec                 (__NR_SVR4 +  11)
+#define __NR_SVR4_chdir                        (__NR_SVR4 +  12)
+#define __NR_SVR4_gtime                        (__NR_SVR4 +  13)
+#define __NR_SVR4_mknod                        (__NR_SVR4 +  14)
+#define __NR_SVR4_chmod                        (__NR_SVR4 +  15)
+#define __NR_SVR4_chown                        (__NR_SVR4 +  16)
+#define __NR_SVR4_sbreak               (__NR_SVR4 +  17)
+#define __NR_SVR4_stat                 (__NR_SVR4 +  18)
+#define __NR_SVR4_lseek                        (__NR_SVR4 +  19)
+#define __NR_SVR4_getpid               (__NR_SVR4 +  20)
+#define __NR_SVR4_mount                        (__NR_SVR4 +  21)
+#define __NR_SVR4_umount               (__NR_SVR4 +  22)
+#define __NR_SVR4_setuid               (__NR_SVR4 +  23)
+#define __NR_SVR4_getuid               (__NR_SVR4 +  24)
+#define __NR_SVR4_stime                        (__NR_SVR4 +  25)
+#define __NR_SVR4_ptrace               (__NR_SVR4 +  26)
+#define __NR_SVR4_alarm                        (__NR_SVR4 +  27)
+#define __NR_SVR4_fstat                        (__NR_SVR4 +  28)
+#define __NR_SVR4_pause                        (__NR_SVR4 +  29)
+#define __NR_SVR4_utime                        (__NR_SVR4 +  30)
+#define __NR_SVR4_stty                 (__NR_SVR4 +  31)
+#define __NR_SVR4_gtty                 (__NR_SVR4 +  32)
+#define __NR_SVR4_access               (__NR_SVR4 +  33)
+#define __NR_SVR4_nice                 (__NR_SVR4 +  34)
+#define __NR_SVR4_statfs               (__NR_SVR4 +  35)
+#define __NR_SVR4_sync                 (__NR_SVR4 +  36)
+#define __NR_SVR4_kill                 (__NR_SVR4 +  37)
+#define __NR_SVR4_fstatfs              (__NR_SVR4 +  38)
+#define __NR_SVR4_setpgrp              (__NR_SVR4 +  39)
+#define __NR_SVR4_cxenix               (__NR_SVR4 +  40)
+#define __NR_SVR4_dup                  (__NR_SVR4 +  41)
+#define __NR_SVR4_pipe                 (__NR_SVR4 +  42)
+#define __NR_SVR4_times                        (__NR_SVR4 +  43)
+#define __NR_SVR4_profil               (__NR_SVR4 +  44)
+#define __NR_SVR4_plock                        (__NR_SVR4 +  45)
+#define __NR_SVR4_setgid               (__NR_SVR4 +  46)
+#define __NR_SVR4_getgid               (__NR_SVR4 +  47)
+#define __NR_SVR4_sig                  (__NR_SVR4 +  48)
+#define __NR_SVR4_msgsys               (__NR_SVR4 +  49)
+#define __NR_SVR4_sysmips              (__NR_SVR4 +  50)
+#define __NR_SVR4_sysacct              (__NR_SVR4 +  51)
+#define __NR_SVR4_shmsys               (__NR_SVR4 +  52)
+#define __NR_SVR4_semsys               (__NR_SVR4 +  53)
+#define __NR_SVR4_ioctl                        (__NR_SVR4 +  54)
+#define __NR_SVR4_uadmin               (__NR_SVR4 +  55)
+#define __NR_SVR4_exch                         (__NR_SVR4 +  56)
+#define __NR_SVR4_utssys               (__NR_SVR4 +  57)
+#define __NR_SVR4_fsync                        (__NR_SVR4 +  58)
+#define __NR_SVR4_exece                        (__NR_SVR4 +  59)
+#define __NR_SVR4_umask                        (__NR_SVR4 +  60)
+#define __NR_SVR4_chroot               (__NR_SVR4 +  61)
+#define __NR_SVR4_fcntl                        (__NR_SVR4 +  62)
+#define __NR_SVR4_ulimit               (__NR_SVR4 +  63)
+#define __NR_SVR4_reserved1            (__NR_SVR4 +  64)
+#define __NR_SVR4_reserved2            (__NR_SVR4 +  65)
+#define __NR_SVR4_reserved3            (__NR_SVR4 +  66)
+#define __NR_SVR4_reserved4            (__NR_SVR4 +  67)
+#define __NR_SVR4_reserved5            (__NR_SVR4 +  68)
+#define __NR_SVR4_reserved6            (__NR_SVR4 +  69)
+#define __NR_SVR4_advfs                        (__NR_SVR4 +  70)
+#define __NR_SVR4_unadvfs              (__NR_SVR4 +  71)
+#define __NR_SVR4_unused1              (__NR_SVR4 +  72)
+#define __NR_SVR4_unused2              (__NR_SVR4 +  73)
+#define __NR_SVR4_rfstart              (__NR_SVR4 +  74)
+#define __NR_SVR4_unused3              (__NR_SVR4 +  75)
+#define __NR_SVR4_rdebug               (__NR_SVR4 +  76)
+#define __NR_SVR4_rfstop               (__NR_SVR4 +  77)
+#define __NR_SVR4_rfsys                        (__NR_SVR4 +  78)
+#define __NR_SVR4_rmdir                        (__NR_SVR4 +  79)
+#define __NR_SVR4_mkdir                        (__NR_SVR4 +  80)
+#define __NR_SVR4_getdents             (__NR_SVR4 +  81)
+#define __NR_SVR4_libattach            (__NR_SVR4 +  82)
+#define __NR_SVR4_libdetach            (__NR_SVR4 +  83)
+#define __NR_SVR4_sysfs                        (__NR_SVR4 +  84)
+#define __NR_SVR4_getmsg               (__NR_SVR4 +  85)
+#define __NR_SVR4_putmsg               (__NR_SVR4 +  86)
+#define __NR_SVR4_poll                 (__NR_SVR4 +  87)
+#define __NR_SVR4_lstat                        (__NR_SVR4 +  88)
+#define __NR_SVR4_symlink              (__NR_SVR4 +  89)
+#define __NR_SVR4_readlink             (__NR_SVR4 +  90)
+#define __NR_SVR4_setgroups            (__NR_SVR4 +  91)
+#define __NR_SVR4_getgroups            (__NR_SVR4 +  92)
+#define __NR_SVR4_fchmod               (__NR_SVR4 +  93)
+#define __NR_SVR4_fchown               (__NR_SVR4 +  94)
+#define __NR_SVR4_sigprocmask          (__NR_SVR4 +  95)
+#define __NR_SVR4_sigsuspend           (__NR_SVR4 +  96)
+#define __NR_SVR4_sigaltstack          (__NR_SVR4 +  97)
+#define __NR_SVR4_sigaction            (__NR_SVR4 +  98)
+#define __NR_SVR4_sigpending           (__NR_SVR4 +  99)
+#define __NR_SVR4_setcontext           (__NR_SVR4 + 100)
+#define __NR_SVR4_evsys                        (__NR_SVR4 + 101)
+#define __NR_SVR4_evtrapret            (__NR_SVR4 + 102)
+#define __NR_SVR4_statvfs              (__NR_SVR4 + 103)
+#define __NR_SVR4_fstatvfs             (__NR_SVR4 + 104)
+#define __NR_SVR4_reserved7            (__NR_SVR4 + 105)
+#define __NR_SVR4_nfssys               (__NR_SVR4 + 106)
+#define __NR_SVR4_waitid               (__NR_SVR4 + 107)
+#define __NR_SVR4_sigsendset           (__NR_SVR4 + 108)
+#define __NR_SVR4_hrtsys               (__NR_SVR4 + 109)
+#define __NR_SVR4_acancel              (__NR_SVR4 + 110)
+#define __NR_SVR4_async                        (__NR_SVR4 + 111)
+#define __NR_SVR4_priocntlset          (__NR_SVR4 + 112)
+#define __NR_SVR4_pathconf             (__NR_SVR4 + 113)
+#define __NR_SVR4_mincore              (__NR_SVR4 + 114)
+#define __NR_SVR4_mmap                 (__NR_SVR4 + 115)
+#define __NR_SVR4_mprotect             (__NR_SVR4 + 116)
+#define __NR_SVR4_munmap               (__NR_SVR4 + 117)
+#define __NR_SVR4_fpathconf            (__NR_SVR4 + 118)
+#define __NR_SVR4_vfork                        (__NR_SVR4 + 119)
+#define __NR_SVR4_fchdir               (__NR_SVR4 + 120)
+#define __NR_SVR4_readv                        (__NR_SVR4 + 121)
+#define __NR_SVR4_writev               (__NR_SVR4 + 122)
+#define __NR_SVR4_xstat                        (__NR_SVR4 + 123)
+#define __NR_SVR4_lxstat               (__NR_SVR4 + 124)
+#define __NR_SVR4_fxstat               (__NR_SVR4 + 125)
+#define __NR_SVR4_xmknod               (__NR_SVR4 + 126)
+#define __NR_SVR4_clocal               (__NR_SVR4 + 127)
+#define __NR_SVR4_setrlimit            (__NR_SVR4 + 128)
+#define __NR_SVR4_getrlimit            (__NR_SVR4 + 129)
+#define __NR_SVR4_lchown               (__NR_SVR4 + 130)
+#define __NR_SVR4_memcntl              (__NR_SVR4 + 131)
+#define __NR_SVR4_getpmsg              (__NR_SVR4 + 132)
+#define __NR_SVR4_putpmsg              (__NR_SVR4 + 133)
+#define __NR_SVR4_rename               (__NR_SVR4 + 134)
+#define __NR_SVR4_nuname               (__NR_SVR4 + 135)
+#define __NR_SVR4_setegid              (__NR_SVR4 + 136)
+#define __NR_SVR4_sysconf              (__NR_SVR4 + 137)
+#define __NR_SVR4_adjtime              (__NR_SVR4 + 138)
+#define __NR_SVR4_sysinfo              (__NR_SVR4 + 139)
+#define __NR_SVR4_reserved8            (__NR_SVR4 + 140)
+#define __NR_SVR4_seteuid              (__NR_SVR4 + 141)
+#define __NR_SVR4_PYRAMID_statis       (__NR_SVR4 + 142)
+#define __NR_SVR4_PYRAMID_tuning       (__NR_SVR4 + 143)
+#define __NR_SVR4_PYRAMID_forcerr      (__NR_SVR4 + 144)
+#define __NR_SVR4_PYRAMID_mpcntl       (__NR_SVR4 + 145)
+#define __NR_SVR4_reserved9            (__NR_SVR4 + 146)
+#define __NR_SVR4_reserved10           (__NR_SVR4 + 147)
+#define __NR_SVR4_reserved11           (__NR_SVR4 + 148)
+#define __NR_SVR4_reserved12           (__NR_SVR4 + 149)
+#define __NR_SVR4_reserved13           (__NR_SVR4 + 150)
+#define __NR_SVR4_reserved14           (__NR_SVR4 + 151)
+#define __NR_SVR4_reserved15           (__NR_SVR4 + 152)
+#define __NR_SVR4_reserved16           (__NR_SVR4 + 153)
+#define __NR_SVR4_reserved17           (__NR_SVR4 + 154)
+#define __NR_SVR4_reserved18           (__NR_SVR4 + 155)
+#define __NR_SVR4_reserved19           (__NR_SVR4 + 156)
+#define __NR_SVR4_reserved20           (__NR_SVR4 + 157)
+#define __NR_SVR4_reserved21           (__NR_SVR4 + 158)
+#define __NR_SVR4_reserved22           (__NR_SVR4 + 159)
+#define __NR_SVR4_reserved23           (__NR_SVR4 + 160)
+#define __NR_SVR4_reserved24           (__NR_SVR4 + 161)
+#define __NR_SVR4_reserved25           (__NR_SVR4 + 162)
+#define __NR_SVR4_reserved26           (__NR_SVR4 + 163)
+#define __NR_SVR4_reserved27           (__NR_SVR4 + 164)
+#define __NR_SVR4_reserved28           (__NR_SVR4 + 165)
+#define __NR_SVR4_reserved29           (__NR_SVR4 + 166)
+#define __NR_SVR4_reserved30           (__NR_SVR4 + 167)
+#define __NR_SVR4_reserved31           (__NR_SVR4 + 168)
+#define __NR_SVR4_reserved32           (__NR_SVR4 + 169)
+#define __NR_SVR4_reserved33           (__NR_SVR4 + 170)
+#define __NR_SVR4_reserved34           (__NR_SVR4 + 171)
+#define __NR_SVR4_reserved35           (__NR_SVR4 + 172)
+#define __NR_SVR4_reserved36           (__NR_SVR4 + 173)
+#define __NR_SVR4_reserved37           (__NR_SVR4 + 174)
+#define __NR_SVR4_reserved38           (__NR_SVR4 + 175)
+#define __NR_SVR4_reserved39           (__NR_SVR4 + 176)
+#define __NR_SVR4_reserved40           (__NR_SVR4 + 177)
+#define __NR_SVR4_reserved41           (__NR_SVR4 + 178)
+#define __NR_SVR4_reserved42           (__NR_SVR4 + 179)
+#define __NR_SVR4_reserved43           (__NR_SVR4 + 180)
+#define __NR_SVR4_reserved44           (__NR_SVR4 + 181)
+#define __NR_SVR4_reserved45           (__NR_SVR4 + 182)
+#define __NR_SVR4_reserved46           (__NR_SVR4 + 183)
+#define __NR_SVR4_reserved47           (__NR_SVR4 + 184)
+#define __NR_SVR4_reserved48           (__NR_SVR4 + 185)
+#define __NR_SVR4_reserved49           (__NR_SVR4 + 186)
+#define __NR_SVR4_reserved50           (__NR_SVR4 + 187)
+#define __NR_SVR4_reserved51           (__NR_SVR4 + 188)
+#define __NR_SVR4_reserved52           (__NR_SVR4 + 189)
+#define __NR_SVR4_reserved53           (__NR_SVR4 + 190)
+#define __NR_SVR4_reserved54           (__NR_SVR4 + 191)
+#define __NR_SVR4_reserved55           (__NR_SVR4 + 192)
+#define __NR_SVR4_reserved56           (__NR_SVR4 + 193)
+#define __NR_SVR4_reserved57           (__NR_SVR4 + 194)
+#define __NR_SVR4_reserved58           (__NR_SVR4 + 195)
+#define __NR_SVR4_reserved59           (__NR_SVR4 + 196)
+#define __NR_SVR4_reserved60           (__NR_SVR4 + 197)
+#define __NR_SVR4_reserved61           (__NR_SVR4 + 198)
+#define __NR_SVR4_reserved62           (__NR_SVR4 + 199)
+#define __NR_SVR4_reserved63           (__NR_SVR4 + 200)
+#define __NR_SVR4_aread                        (__NR_SVR4 + 201)
+#define __NR_SVR4_awrite               (__NR_SVR4 + 202)       
+#define __NR_SVR4_listio               (__NR_SVR4 + 203)
+#define __NR_SVR4_mips_acancel         (__NR_SVR4 + 204)
+#define __NR_SVR4_astatus              (__NR_SVR4 + 205)
+#define __NR_SVR4_await                        (__NR_SVR4 + 206)
+#define __NR_SVR4_areadv               (__NR_SVR4 + 207)
+#define __NR_SVR4_awritev              (__NR_SVR4 + 208)
+#define __NR_SVR4_MIPS_reserved1       (__NR_SVR4 + 209)
+#define __NR_SVR4_MIPS_reserved2       (__NR_SVR4 + 210)
+#define __NR_SVR4_MIPS_reserved3       (__NR_SVR4 + 211)
+#define __NR_SVR4_MIPS_reserved4       (__NR_SVR4 + 212)
+#define __NR_SVR4_MIPS_reserved5       (__NR_SVR4 + 213)
+#define __NR_SVR4_MIPS_reserved6       (__NR_SVR4 + 214)
+#define __NR_SVR4_MIPS_reserved7       (__NR_SVR4 + 215)
+#define __NR_SVR4_MIPS_reserved8       (__NR_SVR4 + 216)
+#define __NR_SVR4_MIPS_reserved9       (__NR_SVR4 + 217)
+#define __NR_SVR4_MIPS_reserved10      (__NR_SVR4 + 218)
+#define __NR_SVR4_MIPS_reserved11      (__NR_SVR4 + 219)
+#define __NR_SVR4_MIPS_reserved12      (__NR_SVR4 + 220)
+#define __NR_SVR4_CDC_reserved1                (__NR_SVR4 + 221)
+#define __NR_SVR4_CDC_reserved2                (__NR_SVR4 + 222)
+#define __NR_SVR4_CDC_reserved3                (__NR_SVR4 + 223)
+#define __NR_SVR4_CDC_reserved4                (__NR_SVR4 + 224)
+#define __NR_SVR4_CDC_reserved5                (__NR_SVR4 + 225)
+#define __NR_SVR4_CDC_reserved6                (__NR_SVR4 + 226)
+#define __NR_SVR4_CDC_reserved7                (__NR_SVR4 + 227)
+#define __NR_SVR4_CDC_reserved8                (__NR_SVR4 + 228)
+#define __NR_SVR4_CDC_reserved9                (__NR_SVR4 + 229)
+#define __NR_SVR4_CDC_reserved10       (__NR_SVR4 + 230)
+#define __NR_SVR4_CDC_reserved11       (__NR_SVR4 + 231)
+#define __NR_SVR4_CDC_reserved12       (__NR_SVR4 + 232)
+#define __NR_SVR4_CDC_reserved13       (__NR_SVR4 + 233)
+#define __NR_SVR4_CDC_reserved14       (__NR_SVR4 + 234)
+#define __NR_SVR4_CDC_reserved15       (__NR_SVR4 + 235)
+#define __NR_SVR4_CDC_reserved16       (__NR_SVR4 + 236)
+#define __NR_SVR4_CDC_reserved17       (__NR_SVR4 + 237)
+#define __NR_SVR4_CDC_reserved18       (__NR_SVR4 + 238)
+#define __NR_SVR4_CDC_reserved19       (__NR_SVR4 + 239)
+#define __NR_SVR4_CDC_reserved20       (__NR_SVR4 + 240)
+
+/*
+ * SYS V syscalls are in the range from 1000 to 1999
+ */
+#define __NR_SYSV                      1000
+#define __NR_SYSV_syscall              (__NR_SYSV +   0)
+#define __NR_SYSV_exit                 (__NR_SYSV +   1)
+#define __NR_SYSV_fork                 (__NR_SYSV +   2)
+#define __NR_SYSV_read                 (__NR_SYSV +   3)
+#define __NR_SYSV_write                        (__NR_SYSV +   4)
+#define __NR_SYSV_open                 (__NR_SYSV +   5)
+#define __NR_SYSV_close                        (__NR_SYSV +   6)
+#define __NR_SYSV_wait                 (__NR_SYSV +   7)
+#define __NR_SYSV_creat                        (__NR_SYSV +   8)
+#define __NR_SYSV_link                 (__NR_SYSV +   9)
+#define __NR_SYSV_unlink               (__NR_SYSV +  10)
+#define __NR_SYSV_execv                        (__NR_SYSV +  11)
+#define __NR_SYSV_chdir                        (__NR_SYSV +  12)
+#define __NR_SYSV_time                 (__NR_SYSV +  13)
+#define __NR_SYSV_mknod                        (__NR_SYSV +  14)
+#define __NR_SYSV_chmod                        (__NR_SYSV +  15)
+#define __NR_SYSV_chown                        (__NR_SYSV +  16)
+#define __NR_SYSV_brk                  (__NR_SYSV +  17)
+#define __NR_SYSV_stat                 (__NR_SYSV +  18)
+#define __NR_SYSV_lseek                        (__NR_SYSV +  19)
+#define __NR_SYSV_getpid               (__NR_SYSV +  20)
+#define __NR_SYSV_mount                        (__NR_SYSV +  21)
+#define __NR_SYSV_umount               (__NR_SYSV +  22)
+#define __NR_SYSV_setuid               (__NR_SYSV +  23)
+#define __NR_SYSV_getuid               (__NR_SYSV +  24)
+#define __NR_SYSV_stime                        (__NR_SYSV +  25)
+#define __NR_SYSV_ptrace               (__NR_SYSV +  26)
+#define __NR_SYSV_alarm                        (__NR_SYSV +  27)
+#define __NR_SYSV_fstat                        (__NR_SYSV +  28)
+#define __NR_SYSV_pause                        (__NR_SYSV +  29)
+#define __NR_SYSV_utime                        (__NR_SYSV +  30)
+#define __NR_SYSV_stty                 (__NR_SYSV +  31)
+#define __NR_SYSV_gtty                 (__NR_SYSV +  32)
+#define __NR_SYSV_access               (__NR_SYSV +  33)
+#define __NR_SYSV_nice                 (__NR_SYSV +  34)
+#define __NR_SYSV_statfs               (__NR_SYSV +  35)
+#define __NR_SYSV_sync                 (__NR_SYSV +  36)
+#define __NR_SYSV_kill                 (__NR_SYSV +  37)
+#define __NR_SYSV_fstatfs              (__NR_SYSV +  38)
+#define __NR_SYSV_setpgrp              (__NR_SYSV +  39)
+#define __NR_SYSV_syssgi               (__NR_SYSV +  40)
+#define __NR_SYSV_dup                  (__NR_SYSV +  41)
+#define __NR_SYSV_pipe                 (__NR_SYSV +  42)
+#define __NR_SYSV_times                        (__NR_SYSV +  43)
+#define __NR_SYSV_profil               (__NR_SYSV +  44)
+#define __NR_SYSV_plock                        (__NR_SYSV +  45)
+#define __NR_SYSV_setgid               (__NR_SYSV +  46)
+#define __NR_SYSV_getgid               (__NR_SYSV +  47)
+#define __NR_SYSV_sig                  (__NR_SYSV +  48)
+#define __NR_SYSV_msgsys               (__NR_SYSV +  49)
+#define __NR_SYSV_sysmips              (__NR_SYSV +  50)
+#define __NR_SYSV_acct                 (__NR_SYSV +  51)
+#define __NR_SYSV_shmsys               (__NR_SYSV +  52)
+#define __NR_SYSV_semsys               (__NR_SYSV +  53)
+#define __NR_SYSV_ioctl                        (__NR_SYSV +  54)
+#define __NR_SYSV_uadmin               (__NR_SYSV +  55)
+#define __NR_SYSV_sysmp                        (__NR_SYSV +  56)
+#define __NR_SYSV_utssys               (__NR_SYSV +  57)
+#define __NR_SYSV_USG_reserved1                (__NR_SYSV +  58)
+#define __NR_SYSV_execve               (__NR_SYSV +  59)
+#define __NR_SYSV_umask                        (__NR_SYSV +  60)
+#define __NR_SYSV_chroot               (__NR_SYSV +  61)
+#define __NR_SYSV_fcntl                        (__NR_SYSV +  62)
+#define __NR_SYSV_ulimit               (__NR_SYSV +  63)
+#define __NR_SYSV_SAFARI4_reserved1    (__NR_SYSV +  64)
+#define __NR_SYSV_SAFARI4_reserved2    (__NR_SYSV +  65)
+#define __NR_SYSV_SAFARI4_reserved3    (__NR_SYSV +  66)
+#define __NR_SYSV_SAFARI4_reserved4    (__NR_SYSV +  67)
+#define __NR_SYSV_SAFARI4_reserved5    (__NR_SYSV +  68)
+#define __NR_SYSV_SAFARI4_reserved6    (__NR_SYSV +  69)
+#define __NR_SYSV_advfs                        (__NR_SYSV +  70)
+#define __NR_SYSV_unadvfs              (__NR_SYSV +  71)
+#define __NR_SYSV_rmount               (__NR_SYSV +  72)
+#define __NR_SYSV_rumount              (__NR_SYSV +  73)
+#define __NR_SYSV_rfstart              (__NR_SYSV +  74)
+#define __NR_SYSV_getrlimit64          (__NR_SYSV +  75)
+#define __NR_SYSV_setrlimit64          (__NR_SYSV +  76)
+#define __NR_SYSV_nanosleep            (__NR_SYSV +  77)
+#define __NR_SYSV_lseek64              (__NR_SYSV +  78)
+#define __NR_SYSV_rmdir                        (__NR_SYSV +  79)
+#define __NR_SYSV_mkdir                        (__NR_SYSV +  80)
+#define __NR_SYSV_getdents             (__NR_SYSV +  81)
+#define __NR_SYSV_sginap               (__NR_SYSV +  82)
+#define __NR_SYSV_sgikopt              (__NR_SYSV +  83)
+#define __NR_SYSV_sysfs                        (__NR_SYSV +  84)
+#define __NR_SYSV_getmsg               (__NR_SYSV +  85)
+#define __NR_SYSV_putmsg               (__NR_SYSV +  86)
+#define __NR_SYSV_poll                 (__NR_SYSV +  87)
+#define __NR_SYSV_sigreturn            (__NR_SYSV +  88)
+#define __NR_SYSV_accept               (__NR_SYSV +  89)
+#define __NR_SYSV_bind                 (__NR_SYSV +  90)
+#define __NR_SYSV_connect              (__NR_SYSV +  91)
+#define __NR_SYSV_gethostid            (__NR_SYSV +  92)
+#define __NR_SYSV_getpeername          (__NR_SYSV +  93)
+#define __NR_SYSV_getsockname          (__NR_SYSV +  94)
+#define __NR_SYSV_getsockopt           (__NR_SYSV +  95)
+#define __NR_SYSV_listen               (__NR_SYSV +  96)
+#define __NR_SYSV_recv                 (__NR_SYSV +  97)
+#define __NR_SYSV_recvfrom             (__NR_SYSV +  98)
+#define __NR_SYSV_recvmsg              (__NR_SYSV +  99)
+#define __NR_SYSV_select               (__NR_SYSV + 100)
+#define __NR_SYSV_send                 (__NR_SYSV + 101)
+#define __NR_SYSV_sendmsg              (__NR_SYSV + 102)
+#define __NR_SYSV_sendto               (__NR_SYSV + 103)
+#define __NR_SYSV_sethostid            (__NR_SYSV + 104)
+#define __NR_SYSV_setsockopt           (__NR_SYSV + 105)
+#define __NR_SYSV_shutdown             (__NR_SYSV + 106)
+#define __NR_SYSV_socket               (__NR_SYSV + 107)
+#define __NR_SYSV_gethostname          (__NR_SYSV + 108)
+#define __NR_SYSV_sethostname          (__NR_SYSV + 109)
+#define __NR_SYSV_getdomainname                (__NR_SYSV + 110)
+#define __NR_SYSV_setdomainname                (__NR_SYSV + 111)
+#define __NR_SYSV_truncate             (__NR_SYSV + 112)
+#define __NR_SYSV_ftruncate            (__NR_SYSV + 113)
+#define __NR_SYSV_rename               (__NR_SYSV + 114)
+#define __NR_SYSV_symlink              (__NR_SYSV + 115)
+#define __NR_SYSV_readlink             (__NR_SYSV + 116)
+#define __NR_SYSV_lstat                        (__NR_SYSV + 117)
+#define __NR_SYSV_nfsmount             (__NR_SYSV + 118)
+#define __NR_SYSV_nfssvc               (__NR_SYSV + 119)
+#define __NR_SYSV_getfh                        (__NR_SYSV + 120)
+#define __NR_SYSV_async_daemon         (__NR_SYSV + 121)
+#define __NR_SYSV_exportfs             (__NR_SYSV + 122)
+#define __NR_SYSV_setregid             (__NR_SYSV + 123)
+#define __NR_SYSV_setreuid             (__NR_SYSV + 124)
+#define __NR_SYSV_getitimer            (__NR_SYSV + 125)
+#define __NR_SYSV_setitimer            (__NR_SYSV + 126)
+#define __NR_SYSV_adjtime              (__NR_SYSV + 127)
+#define __NR_SYSV_BSD_getime           (__NR_SYSV + 128)
+#define __NR_SYSV_sproc                        (__NR_SYSV + 129)
+#define __NR_SYSV_prctl                        (__NR_SYSV + 130)
+#define __NR_SYSV_procblk              (__NR_SYSV + 131)
+#define __NR_SYSV_sprocsp              (__NR_SYSV + 132)
+#define __NR_SYSV_sgigsc               (__NR_SYSV + 133)
+#define __NR_SYSV_mmap                 (__NR_SYSV + 134)
+#define __NR_SYSV_munmap               (__NR_SYSV + 135)
+#define __NR_SYSV_mprotect             (__NR_SYSV + 136)
+#define __NR_SYSV_msync                        (__NR_SYSV + 137)
+#define __NR_SYSV_madvise              (__NR_SYSV + 138)
+#define __NR_SYSV_pagelock             (__NR_SYSV + 139)
+#define __NR_SYSV_getpagesize          (__NR_SYSV + 140)
+#define __NR_SYSV_quotactl             (__NR_SYSV + 141)
+#define __NR_SYSV_libdetach            (__NR_SYSV + 142)
+#define __NR_SYSV_BSDgetpgrp           (__NR_SYSV + 143)
+#define __NR_SYSV_BSDsetpgrp           (__NR_SYSV + 144)
+#define __NR_SYSV_vhangup              (__NR_SYSV + 145)
+#define __NR_SYSV_fsync                        (__NR_SYSV + 146)
+#define __NR_SYSV_fchdir               (__NR_SYSV + 147)
+#define __NR_SYSV_getrlimit            (__NR_SYSV + 148)
+#define __NR_SYSV_setrlimit            (__NR_SYSV + 149)
+#define __NR_SYSV_cacheflush           (__NR_SYSV + 150)
+#define __NR_SYSV_cachectl             (__NR_SYSV + 151)
+#define __NR_SYSV_fchown               (__NR_SYSV + 152)
+#define __NR_SYSV_fchmod               (__NR_SYSV + 153)
+#define __NR_SYSV_wait3                        (__NR_SYSV + 154)
+#define __NR_SYSV_socketpair           (__NR_SYSV + 155)
+#define __NR_SYSV_sysinfo              (__NR_SYSV + 156)
+#define __NR_SYSV_nuname               (__NR_SYSV + 157)
+#define __NR_SYSV_xstat                        (__NR_SYSV + 158)
+#define __NR_SYSV_lxstat               (__NR_SYSV + 159)
+#define __NR_SYSV_fxstat               (__NR_SYSV + 160)
+#define __NR_SYSV_xmknod               (__NR_SYSV + 161)
+#define __NR_SYSV_ksigaction           (__NR_SYSV + 162)
+#define __NR_SYSV_sigpending           (__NR_SYSV + 163)
+#define __NR_SYSV_sigprocmask          (__NR_SYSV + 164)
+#define __NR_SYSV_sigsuspend           (__NR_SYSV + 165)
+#define __NR_SYSV_sigpoll              (__NR_SYSV + 166)
+#define __NR_SYSV_swapctl              (__NR_SYSV + 167)
+#define __NR_SYSV_getcontext           (__NR_SYSV + 168)
+#define __NR_SYSV_setcontext           (__NR_SYSV + 169)
+#define __NR_SYSV_waitsys              (__NR_SYSV + 170)
+#define __NR_SYSV_sigstack             (__NR_SYSV + 171)
+#define __NR_SYSV_sigaltstack          (__NR_SYSV + 172)
+#define __NR_SYSV_sigsendset           (__NR_SYSV + 173)
+#define __NR_SYSV_statvfs              (__NR_SYSV + 174)
+#define __NR_SYSV_fstatvfs             (__NR_SYSV + 175)
+#define __NR_SYSV_getpmsg              (__NR_SYSV + 176)
+#define __NR_SYSV_putpmsg              (__NR_SYSV + 177)
+#define __NR_SYSV_lchown               (__NR_SYSV + 178)
+#define __NR_SYSV_priocntl             (__NR_SYSV + 179)
+#define __NR_SYSV_ksigqueue            (__NR_SYSV + 180)
+#define __NR_SYSV_readv                        (__NR_SYSV + 181)
+#define __NR_SYSV_writev               (__NR_SYSV + 182)
+#define __NR_SYSV_truncate64           (__NR_SYSV + 183)
+#define __NR_SYSV_ftruncate64          (__NR_SYSV + 184)
+#define __NR_SYSV_mmap64               (__NR_SYSV + 185)
+#define __NR_SYSV_dmi                  (__NR_SYSV + 186)
+#define __NR_SYSV_pread                        (__NR_SYSV + 187)
+#define __NR_SYSV_pwrite               (__NR_SYSV + 188)
+
+/*
+ * BSD 4.3 syscalls are in the range from 2000 to 2999
+ */
+#define __NR_BSD43                     2000
+#define __NR_BSD43_syscall             (__NR_BSD43 +   0)
+#define __NR_BSD43_exit                        (__NR_BSD43 +   1)
+#define __NR_BSD43_fork                        (__NR_BSD43 +   2)
+#define __NR_BSD43_read                        (__NR_BSD43 +   3)
+#define __NR_BSD43_write               (__NR_BSD43 +   4)
+#define __NR_BSD43_open                        (__NR_BSD43 +   5)
+#define __NR_BSD43_close               (__NR_BSD43 +   6)
+#define __NR_BSD43_wait                        (__NR_BSD43 +   7)
+#define __NR_BSD43_creat               (__NR_BSD43 +   8)
+#define __NR_BSD43_link                        (__NR_BSD43 +   9)
+#define __NR_BSD43_unlink              (__NR_BSD43 +  10)
+#define __NR_BSD43_exec                        (__NR_BSD43 +  11)
+#define __NR_BSD43_chdir               (__NR_BSD43 +  12)
+#define __NR_BSD43_time                        (__NR_BSD43 +  13)
+#define __NR_BSD43_mknod               (__NR_BSD43 +  14)
+#define __NR_BSD43_chmod               (__NR_BSD43 +  15)
+#define __NR_BSD43_chown               (__NR_BSD43 +  16)
+#define __NR_BSD43_sbreak              (__NR_BSD43 +  17)
+#define __NR_BSD43_oldstat             (__NR_BSD43 +  18)
+#define __NR_BSD43_lseek               (__NR_BSD43 +  19)
+#define __NR_BSD43_getpid              (__NR_BSD43 +  20)
+#define __NR_BSD43_oldmount            (__NR_BSD43 +  21)
+#define __NR_BSD43_umount              (__NR_BSD43 +  22)
+#define __NR_BSD43_setuid              (__NR_BSD43 +  23)
+#define __NR_BSD43_getuid              (__NR_BSD43 +  24)
+#define __NR_BSD43_stime               (__NR_BSD43 +  25)
+#define __NR_BSD43_ptrace              (__NR_BSD43 +  26)
+#define __NR_BSD43_alarm               (__NR_BSD43 +  27)
+#define __NR_BSD43_oldfstat            (__NR_BSD43 +  28)
+#define __NR_BSD43_pause               (__NR_BSD43 +  29)
+#define __NR_BSD43_utime               (__NR_BSD43 +  30)
+#define __NR_BSD43_stty                        (__NR_BSD43 +  31)
+#define __NR_BSD43_gtty                        (__NR_BSD43 +  32)
+#define __NR_BSD43_access              (__NR_BSD43 +  33)
+#define __NR_BSD43_nice                        (__NR_BSD43 +  34)
+#define __NR_BSD43_ftime               (__NR_BSD43 +  35)
+#define __NR_BSD43_sync                        (__NR_BSD43 +  36)
+#define __NR_BSD43_kill                        (__NR_BSD43 +  37)
+#define __NR_BSD43_stat                        (__NR_BSD43 +  38)
+#define __NR_BSD43_oldsetpgrp          (__NR_BSD43 +  39)
+#define __NR_BSD43_lstat               (__NR_BSD43 +  40)
+#define __NR_BSD43_dup                 (__NR_BSD43 +  41)
+#define __NR_BSD43_pipe                        (__NR_BSD43 +  42)
+#define __NR_BSD43_times               (__NR_BSD43 +  43)
+#define __NR_BSD43_profil              (__NR_BSD43 +  44)
+#define __NR_BSD43_msgsys              (__NR_BSD43 +  45)
+#define __NR_BSD43_setgid              (__NR_BSD43 +  46)
+#define __NR_BSD43_getgid              (__NR_BSD43 +  47)
+#define __NR_BSD43_ssig                        (__NR_BSD43 +  48)
+#define __NR_BSD43_reserved1           (__NR_BSD43 +  49)
+#define __NR_BSD43_reserved2           (__NR_BSD43 +  50)
+#define __NR_BSD43_sysacct             (__NR_BSD43 +  51)
+#define __NR_BSD43_phys                        (__NR_BSD43 +  52)
+#define __NR_BSD43_lock                        (__NR_BSD43 +  53)
+#define __NR_BSD43_ioctl               (__NR_BSD43 +  54)
+#define __NR_BSD43_reboot              (__NR_BSD43 +  55)
+#define __NR_BSD43_mpxchan             (__NR_BSD43 +  56)
+#define __NR_BSD43_symlink             (__NR_BSD43 +  57)
+#define __NR_BSD43_readlink            (__NR_BSD43 +  58)
+#define __NR_BSD43_execve              (__NR_BSD43 +  59)
+#define __NR_BSD43_umask               (__NR_BSD43 +  60)
+#define __NR_BSD43_chroot              (__NR_BSD43 +  61)
+#define __NR_BSD43_fstat               (__NR_BSD43 +  62)
+#define __NR_BSD43_reserved3           (__NR_BSD43 +  63)
+#define __NR_BSD43_getpagesize         (__NR_BSD43 +  64)
+#define __NR_BSD43_mremap              (__NR_BSD43 +  65)
+#define __NR_BSD43_vfork               (__NR_BSD43 +  66)
+#define __NR_BSD43_vread               (__NR_BSD43 +  67)
+#define __NR_BSD43_vwrite              (__NR_BSD43 +  68)
+#define __NR_BSD43_sbrk                        (__NR_BSD43 +  69)
+#define __NR_BSD43_sstk                        (__NR_BSD43 +  70)
+#define __NR_BSD43_mmap                        (__NR_BSD43 +  71)
+#define __NR_BSD43_vadvise             (__NR_BSD43 +  72)
+#define __NR_BSD43_munmap              (__NR_BSD43 +  73)
+#define __NR_BSD43_mprotect            (__NR_BSD43 +  74)
+#define __NR_BSD43_madvise             (__NR_BSD43 +  75)
+#define __NR_BSD43_vhangup             (__NR_BSD43 +  76)
+#define __NR_BSD43_vlimit              (__NR_BSD43 +  77)
+#define __NR_BSD43_mincore             (__NR_BSD43 +  78)
+#define __NR_BSD43_getgroups           (__NR_BSD43 +  79)
+#define __NR_BSD43_setgroups           (__NR_BSD43 +  80)
+#define __NR_BSD43_getpgrp             (__NR_BSD43 +  81)
+#define __NR_BSD43_setpgrp             (__NR_BSD43 +  82)
+#define __NR_BSD43_setitimer           (__NR_BSD43 +  83)
+#define __NR_BSD43_wait3               (__NR_BSD43 +  84)
+#define __NR_BSD43_swapon              (__NR_BSD43 +  85)
+#define __NR_BSD43_getitimer           (__NR_BSD43 +  86)
+#define __NR_BSD43_gethostname         (__NR_BSD43 +  87)
+#define __NR_BSD43_sethostname         (__NR_BSD43 +  88)
+#define __NR_BSD43_getdtablesize       (__NR_BSD43 +  89)
+#define __NR_BSD43_dup2                        (__NR_BSD43 +  90)
+#define __NR_BSD43_getdopt             (__NR_BSD43 +  91)
+#define __NR_BSD43_fcntl               (__NR_BSD43 +  92)
+#define __NR_BSD43_select              (__NR_BSD43 +  93)
+#define __NR_BSD43_setdopt             (__NR_BSD43 +  94)
+#define __NR_BSD43_fsync               (__NR_BSD43 +  95)
+#define __NR_BSD43_setpriority         (__NR_BSD43 +  96)
+#define __NR_BSD43_socket              (__NR_BSD43 +  97)
+#define __NR_BSD43_connect             (__NR_BSD43 +  98)
+#define __NR_BSD43_oldaccept           (__NR_BSD43 +  99)
+#define __NR_BSD43_getpriority         (__NR_BSD43 + 100)
+#define __NR_BSD43_send                        (__NR_BSD43 + 101)
+#define __NR_BSD43_recv                        (__NR_BSD43 + 102)
+#define __NR_BSD43_sigreturn           (__NR_BSD43 + 103)
+#define __NR_BSD43_bind                        (__NR_BSD43 + 104)
+#define __NR_BSD43_setsockopt          (__NR_BSD43 + 105)
+#define __NR_BSD43_listen              (__NR_BSD43 + 106)
+#define __NR_BSD43_vtimes              (__NR_BSD43 + 107)
+#define __NR_BSD43_sigvec              (__NR_BSD43 + 108)
+#define __NR_BSD43_sigblock            (__NR_BSD43 + 109)
+#define __NR_BSD43_sigsetmask          (__NR_BSD43 + 110)
+#define __NR_BSD43_sigpause            (__NR_BSD43 + 111)
+#define __NR_BSD43_sigstack            (__NR_BSD43 + 112)
+#define __NR_BSD43_oldrecvmsg          (__NR_BSD43 + 113)
+#define __NR_BSD43_oldsendmsg          (__NR_BSD43 + 114)
+#define __NR_BSD43_vtrace              (__NR_BSD43 + 115)
+#define __NR_BSD43_gettimeofday                (__NR_BSD43 + 116)
+#define __NR_BSD43_getrusage           (__NR_BSD43 + 117)
+#define __NR_BSD43_getsockopt          (__NR_BSD43 + 118)
+#define __NR_BSD43_reserved4           (__NR_BSD43 + 119)
+#define __NR_BSD43_readv               (__NR_BSD43 + 120)
+#define __NR_BSD43_writev              (__NR_BSD43 + 121)
+#define __NR_BSD43_settimeofday                (__NR_BSD43 + 122)
+#define __NR_BSD43_fchown              (__NR_BSD43 + 123)
+#define __NR_BSD43_fchmod              (__NR_BSD43 + 124)
+#define __NR_BSD43_oldrecvfrom         (__NR_BSD43 + 125)
+#define __NR_BSD43_setreuid            (__NR_BSD43 + 126)
+#define __NR_BSD43_setregid            (__NR_BSD43 + 127)
+#define __NR_BSD43_rename              (__NR_BSD43 + 128)
+#define __NR_BSD43_truncate            (__NR_BSD43 + 129)
+#define __NR_BSD43_ftruncate           (__NR_BSD43 + 130)
+#define __NR_BSD43_flock               (__NR_BSD43 + 131)
+#define __NR_BSD43_semsys              (__NR_BSD43 + 132)
+#define __NR_BSD43_sendto              (__NR_BSD43 + 133)
+#define __NR_BSD43_shutdown            (__NR_BSD43 + 134)
+#define __NR_BSD43_socketpair          (__NR_BSD43 + 135)
+#define __NR_BSD43_mkdir               (__NR_BSD43 + 136)
+#define __NR_BSD43_rmdir               (__NR_BSD43 + 137)
+#define __NR_BSD43_utimes              (__NR_BSD43 + 138)
+#define __NR_BSD43_sigcleanup          (__NR_BSD43 + 139)
+#define __NR_BSD43_adjtime             (__NR_BSD43 + 140)
+#define __NR_BSD43_oldgetpeername      (__NR_BSD43 + 141)
+#define __NR_BSD43_gethostid           (__NR_BSD43 + 142)
+#define __NR_BSD43_sethostid           (__NR_BSD43 + 143)
+#define __NR_BSD43_getrlimit           (__NR_BSD43 + 144)
+#define __NR_BSD43_setrlimit           (__NR_BSD43 + 145)
+#define __NR_BSD43_killpg              (__NR_BSD43 + 146)
+#define __NR_BSD43_shmsys              (__NR_BSD43 + 147)
+#define __NR_BSD43_quota               (__NR_BSD43 + 148)
+#define __NR_BSD43_qquota              (__NR_BSD43 + 149)
+#define __NR_BSD43_oldgetsockname      (__NR_BSD43 + 150)
+#define __NR_BSD43_sysmips             (__NR_BSD43 + 151)
+#define __NR_BSD43_cacheflush          (__NR_BSD43 + 152)
+#define __NR_BSD43_cachectl            (__NR_BSD43 + 153)
+#define __NR_BSD43_debug               (__NR_BSD43 + 154)
+#define __NR_BSD43_reserved5           (__NR_BSD43 + 155)
+#define __NR_BSD43_reserved6           (__NR_BSD43 + 156)
+#define __NR_BSD43_nfs_mount           (__NR_BSD43 + 157)
+#define __NR_BSD43_nfs_svc             (__NR_BSD43 + 158)
+#define __NR_BSD43_getdirentries       (__NR_BSD43 + 159)
+#define __NR_BSD43_statfs              (__NR_BSD43 + 160)
+#define __NR_BSD43_fstatfs             (__NR_BSD43 + 161)
+#define __NR_BSD43_unmount             (__NR_BSD43 + 162)
+#define __NR_BSD43_async_daemon                (__NR_BSD43 + 163)
+#define __NR_BSD43_nfs_getfh           (__NR_BSD43 + 164)
+#define __NR_BSD43_getdomainname       (__NR_BSD43 + 165)
+#define __NR_BSD43_setdomainname       (__NR_BSD43 + 166)
+#define __NR_BSD43_pcfs_mount          (__NR_BSD43 + 167)
+#define __NR_BSD43_quotactl            (__NR_BSD43 + 168)
+#define __NR_BSD43_oldexportfs         (__NR_BSD43 + 169)
+#define __NR_BSD43_smount              (__NR_BSD43 + 170)
+#define __NR_BSD43_mipshwconf          (__NR_BSD43 + 171)
+#define __NR_BSD43_exportfs            (__NR_BSD43 + 172)
+#define __NR_BSD43_nfsfh_open          (__NR_BSD43 + 173)
+#define __NR_BSD43_libattach           (__NR_BSD43 + 174)
+#define __NR_BSD43_libdetach           (__NR_BSD43 + 175)
+#define __NR_BSD43_accept              (__NR_BSD43 + 176)
+#define __NR_BSD43_reserved7           (__NR_BSD43 + 177)
+#define __NR_BSD43_reserved8           (__NR_BSD43 + 178)
+#define __NR_BSD43_recvmsg             (__NR_BSD43 + 179)
+#define __NR_BSD43_recvfrom            (__NR_BSD43 + 180)
+#define __NR_BSD43_sendmsg             (__NR_BSD43 + 181)
+#define __NR_BSD43_getpeername         (__NR_BSD43 + 182)
+#define __NR_BSD43_getsockname         (__NR_BSD43 + 183)
+#define __NR_BSD43_aread               (__NR_BSD43 + 184)
+#define __NR_BSD43_awrite              (__NR_BSD43 + 185)
+#define __NR_BSD43_listio              (__NR_BSD43 + 186)
+#define __NR_BSD43_acancel             (__NR_BSD43 + 187)
+#define __NR_BSD43_astatus             (__NR_BSD43 + 188)
+#define __NR_BSD43_await               (__NR_BSD43 + 189)
+#define __NR_BSD43_areadv              (__NR_BSD43 + 190)
+#define __NR_BSD43_awritev             (__NR_BSD43 + 191)
+
+/*
+ * POSIX syscalls are in the range from 3000 to 3999
+ */
+#define __NR_POSIX                     3000
+#define __NR_POSIX_syscall             (__NR_POSIX +   0)
+#define __NR_POSIX_exit                        (__NR_POSIX +   1)
+#define __NR_POSIX_fork                        (__NR_POSIX +   2)
+#define __NR_POSIX_read                        (__NR_POSIX +   3)
+#define __NR_POSIX_write               (__NR_POSIX +   4)
+#define __NR_POSIX_open                        (__NR_POSIX +   5)
+#define __NR_POSIX_close               (__NR_POSIX +   6)
+#define __NR_POSIX_wait                        (__NR_POSIX +   7)
+#define __NR_POSIX_creat               (__NR_POSIX +   8)
+#define __NR_POSIX_link                        (__NR_POSIX +   9)
+#define __NR_POSIX_unlink              (__NR_POSIX +  10)
+#define __NR_POSIX_exec                        (__NR_POSIX +  11)
+#define __NR_POSIX_chdir               (__NR_POSIX +  12)
+#define __NR_POSIX_gtime               (__NR_POSIX +  13)
+#define __NR_POSIX_mknod               (__NR_POSIX +  14)
+#define __NR_POSIX_chmod               (__NR_POSIX +  15)
+#define __NR_POSIX_chown               (__NR_POSIX +  16)
+#define __NR_POSIX_sbreak              (__NR_POSIX +  17)
+#define __NR_POSIX_stat                        (__NR_POSIX +  18)
+#define __NR_POSIX_lseek               (__NR_POSIX +  19)
+#define __NR_POSIX_getpid              (__NR_POSIX +  20)
+#define __NR_POSIX_mount               (__NR_POSIX +  21)
+#define __NR_POSIX_umount              (__NR_POSIX +  22)
+#define __NR_POSIX_setuid              (__NR_POSIX +  23)
+#define __NR_POSIX_getuid              (__NR_POSIX +  24)
+#define __NR_POSIX_stime               (__NR_POSIX +  25)
+#define __NR_POSIX_ptrace              (__NR_POSIX +  26)
+#define __NR_POSIX_alarm               (__NR_POSIX +  27)
+#define __NR_POSIX_fstat               (__NR_POSIX +  28)
+#define __NR_POSIX_pause               (__NR_POSIX +  29)
+#define __NR_POSIX_utime               (__NR_POSIX +  30)
+#define __NR_POSIX_stty                        (__NR_POSIX +  31)
+#define __NR_POSIX_gtty                        (__NR_POSIX +  32)
+#define __NR_POSIX_access              (__NR_POSIX +  33)
+#define __NR_POSIX_nice                        (__NR_POSIX +  34)
+#define __NR_POSIX_statfs              (__NR_POSIX +  35)
+#define __NR_POSIX_sync                        (__NR_POSIX +  36)
+#define __NR_POSIX_kill                        (__NR_POSIX +  37)
+#define __NR_POSIX_fstatfs             (__NR_POSIX +  38)
+#define __NR_POSIX_getpgrp             (__NR_POSIX +  39)
+#define __NR_POSIX_syssgi              (__NR_POSIX +  40)
+#define __NR_POSIX_dup                 (__NR_POSIX +  41)
+#define __NR_POSIX_pipe                        (__NR_POSIX +  42)
+#define __NR_POSIX_times               (__NR_POSIX +  43)
+#define __NR_POSIX_profil              (__NR_POSIX +  44)
+#define __NR_POSIX_lock                        (__NR_POSIX +  45)
+#define __NR_POSIX_setgid              (__NR_POSIX +  46)
+#define __NR_POSIX_getgid              (__NR_POSIX +  47)
+#define __NR_POSIX_sig                 (__NR_POSIX +  48)
+#define __NR_POSIX_msgsys              (__NR_POSIX +  49)
+#define __NR_POSIX_sysmips             (__NR_POSIX +  50)
+#define __NR_POSIX_sysacct             (__NR_POSIX +  51)
+#define __NR_POSIX_shmsys              (__NR_POSIX +  52)
+#define __NR_POSIX_semsys              (__NR_POSIX +  53)
+#define __NR_POSIX_ioctl               (__NR_POSIX +  54)
+#define __NR_POSIX_uadmin              (__NR_POSIX +  55)
+#define __NR_POSIX_exch                        (__NR_POSIX +  56)
+#define __NR_POSIX_utssys              (__NR_POSIX +  57)
+#define __NR_POSIX_USG_reserved1       (__NR_POSIX +  58)
+#define __NR_POSIX_exece               (__NR_POSIX +  59)
+#define __NR_POSIX_umask               (__NR_POSIX +  60)
+#define __NR_POSIX_chroot              (__NR_POSIX +  61)
+#define __NR_POSIX_fcntl               (__NR_POSIX +  62)
+#define __NR_POSIX_ulimit              (__NR_POSIX +  63)
+#define __NR_POSIX_SAFARI4_reserved1   (__NR_POSIX +  64)
+#define __NR_POSIX_SAFARI4_reserved2   (__NR_POSIX +  65)
+#define __NR_POSIX_SAFARI4_reserved3   (__NR_POSIX +  66)
+#define __NR_POSIX_SAFARI4_reserved4   (__NR_POSIX +  67)
+#define __NR_POSIX_SAFARI4_reserved5   (__NR_POSIX +  68)
+#define __NR_POSIX_SAFARI4_reserved6   (__NR_POSIX +  69)
+#define __NR_POSIX_advfs               (__NR_POSIX +  70)
+#define __NR_POSIX_unadvfs             (__NR_POSIX +  71)
+#define __NR_POSIX_rmount              (__NR_POSIX +  72)
+#define __NR_POSIX_rumount             (__NR_POSIX +  73)
+#define __NR_POSIX_rfstart             (__NR_POSIX +  74)
+#define __NR_POSIX_reserved1           (__NR_POSIX +  75)
+#define __NR_POSIX_rdebug              (__NR_POSIX +  76)
+#define __NR_POSIX_rfstop              (__NR_POSIX +  77)
+#define __NR_POSIX_rfsys               (__NR_POSIX +  78)
+#define __NR_POSIX_rmdir               (__NR_POSIX +  79)
+#define __NR_POSIX_mkdir               (__NR_POSIX +  80)
+#define __NR_POSIX_getdents            (__NR_POSIX +  81)
+#define __NR_POSIX_sginap              (__NR_POSIX +  82)
+#define __NR_POSIX_sgikopt             (__NR_POSIX +  83)
+#define __NR_POSIX_sysfs               (__NR_POSIX +  84)
+#define __NR_POSIX_getmsg              (__NR_POSIX +  85)
+#define __NR_POSIX_putmsg              (__NR_POSIX +  86)
+#define __NR_POSIX_poll                        (__NR_POSIX +  87)
+#define __NR_POSIX_sigreturn           (__NR_POSIX +  88)
+#define __NR_POSIX_accept              (__NR_POSIX +  89)
+#define __NR_POSIX_bind                        (__NR_POSIX +  90)
+#define __NR_POSIX_connect             (__NR_POSIX +  91)
+#define __NR_POSIX_gethostid           (__NR_POSIX +  92)
+#define __NR_POSIX_getpeername         (__NR_POSIX +  93)
+#define __NR_POSIX_getsockname         (__NR_POSIX +  94)
+#define __NR_POSIX_getsockopt          (__NR_POSIX +  95)
+#define __NR_POSIX_listen              (__NR_POSIX +  96)
+#define __NR_POSIX_recv                        (__NR_POSIX +  97)
+#define __NR_POSIX_recvfrom            (__NR_POSIX +  98)
+#define __NR_POSIX_recvmsg             (__NR_POSIX +  99)
+#define __NR_POSIX_select              (__NR_POSIX + 100)
+#define __NR_POSIX_send                        (__NR_POSIX + 101)
+#define __NR_POSIX_sendmsg             (__NR_POSIX + 102)
+#define __NR_POSIX_sendto              (__NR_POSIX + 103)
+#define __NR_POSIX_sethostid           (__NR_POSIX + 104)
+#define __NR_POSIX_setsockopt          (__NR_POSIX + 105)
+#define __NR_POSIX_shutdown            (__NR_POSIX + 106)
+#define __NR_POSIX_socket              (__NR_POSIX + 107)
+#define __NR_POSIX_gethostname         (__NR_POSIX + 108)
+#define __NR_POSIX_sethostname         (__NR_POSIX + 109)
+#define __NR_POSIX_getdomainname       (__NR_POSIX + 110)
+#define __NR_POSIX_setdomainname       (__NR_POSIX + 111)
+#define __NR_POSIX_truncate            (__NR_POSIX + 112)
+#define __NR_POSIX_ftruncate           (__NR_POSIX + 113)
+#define __NR_POSIX_rename              (__NR_POSIX + 114)
+#define __NR_POSIX_symlink             (__NR_POSIX + 115)
+#define __NR_POSIX_readlink            (__NR_POSIX + 116)
+#define __NR_POSIX_lstat               (__NR_POSIX + 117)
+#define __NR_POSIX_nfs_mount           (__NR_POSIX + 118)
+#define __NR_POSIX_nfs_svc             (__NR_POSIX + 119)
+#define __NR_POSIX_nfs_getfh           (__NR_POSIX + 120)
+#define __NR_POSIX_async_daemon                (__NR_POSIX + 121)
+#define __NR_POSIX_exportfs            (__NR_POSIX + 122)
+#define __NR_POSIX_SGI_setregid                (__NR_POSIX + 123)
+#define __NR_POSIX_SGI_setreuid                (__NR_POSIX + 124)
+#define __NR_POSIX_getitimer           (__NR_POSIX + 125)
+#define __NR_POSIX_setitimer           (__NR_POSIX + 126)
+#define __NR_POSIX_adjtime             (__NR_POSIX + 127)
+#define __NR_POSIX_SGI_bsdgettime      (__NR_POSIX + 128)
+#define __NR_POSIX_SGI_sproc           (__NR_POSIX + 129)
+#define __NR_POSIX_SGI_prctl           (__NR_POSIX + 130)
+#define __NR_POSIX_SGI_blkproc         (__NR_POSIX + 131)
+#define __NR_POSIX_SGI_reserved1       (__NR_POSIX + 132)
+#define __NR_POSIX_SGI_sgigsc          (__NR_POSIX + 133)
+#define __NR_POSIX_SGI_mmap            (__NR_POSIX + 134)
+#define __NR_POSIX_SGI_munmap          (__NR_POSIX + 135)
+#define __NR_POSIX_SGI_mprotect                (__NR_POSIX + 136)
+#define __NR_POSIX_SGI_msync           (__NR_POSIX + 137)
+#define __NR_POSIX_SGI_madvise         (__NR_POSIX + 138)
+#define __NR_POSIX_SGI_mpin            (__NR_POSIX + 139)
+#define __NR_POSIX_SGI_getpagesize     (__NR_POSIX + 140)
+#define __NR_POSIX_SGI_libattach       (__NR_POSIX + 141)
+#define __NR_POSIX_SGI_libdetach       (__NR_POSIX + 142)
+#define __NR_POSIX_SGI_getpgrp         (__NR_POSIX + 143)
+#define __NR_POSIX_SGI_setpgrp         (__NR_POSIX + 144)
+#define __NR_POSIX_SGI_reserved2       (__NR_POSIX + 145)
+#define __NR_POSIX_SGI_reserved3       (__NR_POSIX + 146)
+#define __NR_POSIX_SGI_reserved4       (__NR_POSIX + 147)
+#define __NR_POSIX_SGI_reserved5       (__NR_POSIX + 148)
+#define __NR_POSIX_SGI_reserved6       (__NR_POSIX + 149)
+#define __NR_POSIX_cacheflush          (__NR_POSIX + 150)
+#define __NR_POSIX_cachectl            (__NR_POSIX + 151)
+#define __NR_POSIX_fchown              (__NR_POSIX + 152)
+#define __NR_POSIX_fchmod              (__NR_POSIX + 153)
+#define __NR_POSIX_wait3               (__NR_POSIX + 154)
+#define __NR_POSIX_mmap                        (__NR_POSIX + 155)
+#define __NR_POSIX_munmap              (__NR_POSIX + 156)
+#define __NR_POSIX_madvise             (__NR_POSIX + 157)
+#define __NR_POSIX_BSD_getpagesize     (__NR_POSIX + 158)
+#define __NR_POSIX_setreuid            (__NR_POSIX + 159)
+#define __NR_POSIX_setregid            (__NR_POSIX + 160)
+#define __NR_POSIX_setpgid             (__NR_POSIX + 161)
+#define __NR_POSIX_getgroups           (__NR_POSIX + 162)
+#define __NR_POSIX_setgroups           (__NR_POSIX + 163)
+#define __NR_POSIX_gettimeofday                (__NR_POSIX + 164)
+#define __NR_POSIX_getrusage           (__NR_POSIX + 165)
+#define __NR_POSIX_getrlimit           (__NR_POSIX + 166)
+#define __NR_POSIX_setrlimit           (__NR_POSIX + 167)
+#define __NR_POSIX_waitpid             (__NR_POSIX + 168)
+#define __NR_POSIX_dup2                        (__NR_POSIX + 169)
+#define __NR_POSIX_reserved2           (__NR_POSIX + 170)
+#define __NR_POSIX_reserved3           (__NR_POSIX + 171)
+#define __NR_POSIX_reserved4           (__NR_POSIX + 172)
+#define __NR_POSIX_reserved5           (__NR_POSIX + 173)
+#define __NR_POSIX_reserved6           (__NR_POSIX + 174)
+#define __NR_POSIX_reserved7           (__NR_POSIX + 175)
+#define __NR_POSIX_reserved8           (__NR_POSIX + 176)
+#define __NR_POSIX_reserved9           (__NR_POSIX + 177)
+#define __NR_POSIX_reserved10          (__NR_POSIX + 178)
+#define __NR_POSIX_reserved11          (__NR_POSIX + 179)
+#define __NR_POSIX_reserved12          (__NR_POSIX + 180)
+#define __NR_POSIX_reserved13          (__NR_POSIX + 181)
+#define __NR_POSIX_reserved14          (__NR_POSIX + 182)
+#define __NR_POSIX_reserved15          (__NR_POSIX + 183)
+#define __NR_POSIX_reserved16          (__NR_POSIX + 184)
+#define __NR_POSIX_reserved17          (__NR_POSIX + 185)
+#define __NR_POSIX_reserved18          (__NR_POSIX + 186)
+#define __NR_POSIX_reserved19          (__NR_POSIX + 187)
+#define __NR_POSIX_reserved20          (__NR_POSIX + 188)
+#define __NR_POSIX_reserved21          (__NR_POSIX + 189)
+#define __NR_POSIX_reserved22          (__NR_POSIX + 190)
+#define __NR_POSIX_reserved23          (__NR_POSIX + 191)
+#define __NR_POSIX_reserved24          (__NR_POSIX + 192)
+#define __NR_POSIX_reserved25          (__NR_POSIX + 193)
+#define __NR_POSIX_reserved26          (__NR_POSIX + 194)
+#define __NR_POSIX_reserved27          (__NR_POSIX + 195)
+#define __NR_POSIX_reserved28          (__NR_POSIX + 196)
+#define __NR_POSIX_reserved29          (__NR_POSIX + 197)
+#define __NR_POSIX_reserved30          (__NR_POSIX + 198)
+#define __NR_POSIX_reserved31          (__NR_POSIX + 199)
+#define __NR_POSIX_reserved32          (__NR_POSIX + 200)
+#define __NR_POSIX_reserved33          (__NR_POSIX + 201)
+#define __NR_POSIX_reserved34          (__NR_POSIX + 202)
+#define __NR_POSIX_reserved35          (__NR_POSIX + 203)
+#define __NR_POSIX_reserved36          (__NR_POSIX + 204)
+#define __NR_POSIX_reserved37          (__NR_POSIX + 205)
+#define __NR_POSIX_reserved38          (__NR_POSIX + 206)
+#define __NR_POSIX_reserved39          (__NR_POSIX + 207)
+#define __NR_POSIX_reserved40          (__NR_POSIX + 208)
+#define __NR_POSIX_reserved41          (__NR_POSIX + 209)
+#define __NR_POSIX_reserved42          (__NR_POSIX + 210)
+#define __NR_POSIX_reserved43          (__NR_POSIX + 211)
+#define __NR_POSIX_reserved44          (__NR_POSIX + 212)
+#define __NR_POSIX_reserved45          (__NR_POSIX + 213)
+#define __NR_POSIX_reserved46          (__NR_POSIX + 214)
+#define __NR_POSIX_reserved47          (__NR_POSIX + 215)
+#define __NR_POSIX_reserved48          (__NR_POSIX + 216)
+#define __NR_POSIX_reserved49          (__NR_POSIX + 217)
+#define __NR_POSIX_reserved50          (__NR_POSIX + 218)
+#define __NR_POSIX_reserved51          (__NR_POSIX + 219)
+#define __NR_POSIX_reserved52          (__NR_POSIX + 220)
+#define __NR_POSIX_reserved53          (__NR_POSIX + 221)
+#define __NR_POSIX_reserved54          (__NR_POSIX + 222)
+#define __NR_POSIX_reserved55          (__NR_POSIX + 223)
+#define __NR_POSIX_reserved56          (__NR_POSIX + 224)
+#define __NR_POSIX_reserved57          (__NR_POSIX + 225)
+#define __NR_POSIX_reserved58          (__NR_POSIX + 226)
+#define __NR_POSIX_reserved59          (__NR_POSIX + 227)
+#define __NR_POSIX_reserved60          (__NR_POSIX + 228)
+#define __NR_POSIX_reserved61          (__NR_POSIX + 229)
+#define __NR_POSIX_reserved62          (__NR_POSIX + 230)
+#define __NR_POSIX_reserved63          (__NR_POSIX + 231)
+#define __NR_POSIX_reserved64          (__NR_POSIX + 232)
+#define __NR_POSIX_reserved65          (__NR_POSIX + 233)
+#define __NR_POSIX_reserved66          (__NR_POSIX + 234)
+#define __NR_POSIX_reserved67          (__NR_POSIX + 235)
+#define __NR_POSIX_reserved68          (__NR_POSIX + 236)
+#define __NR_POSIX_reserved69          (__NR_POSIX + 237)
+#define __NR_POSIX_reserved70          (__NR_POSIX + 238)
+#define __NR_POSIX_reserved71          (__NR_POSIX + 239)
+#define __NR_POSIX_reserved72          (__NR_POSIX + 240)
+#define __NR_POSIX_reserved73          (__NR_POSIX + 241)
+#define __NR_POSIX_reserved74          (__NR_POSIX + 242)
+#define __NR_POSIX_reserved75          (__NR_POSIX + 243)
+#define __NR_POSIX_reserved76          (__NR_POSIX + 244)
+#define __NR_POSIX_reserved77          (__NR_POSIX + 245)
+#define __NR_POSIX_reserved78          (__NR_POSIX + 246)
+#define __NR_POSIX_reserved79          (__NR_POSIX + 247)
+#define __NR_POSIX_reserved80          (__NR_POSIX + 248)
+#define __NR_POSIX_reserved81          (__NR_POSIX + 249)
+#define __NR_POSIX_reserved82          (__NR_POSIX + 250)
+#define __NR_POSIX_reserved83          (__NR_POSIX + 251)
+#define __NR_POSIX_reserved84          (__NR_POSIX + 252)
+#define __NR_POSIX_reserved85          (__NR_POSIX + 253)
+#define __NR_POSIX_reserved86          (__NR_POSIX + 254)
+#define __NR_POSIX_reserved87          (__NR_POSIX + 255)
+#define __NR_POSIX_reserved88          (__NR_POSIX + 256)
+#define __NR_POSIX_reserved89          (__NR_POSIX + 257)
+#define __NR_POSIX_reserved90          (__NR_POSIX + 258)
+#define __NR_POSIX_reserved91          (__NR_POSIX + 259)
+#define __NR_POSIX_netboot             (__NR_POSIX + 260)
+#define __NR_POSIX_netunboot           (__NR_POSIX + 261)
+#define __NR_POSIX_rdump               (__NR_POSIX + 262)
+#define __NR_POSIX_setsid              (__NR_POSIX + 263)
+#define __NR_POSIX_getmaxsig           (__NR_POSIX + 264)
+#define __NR_POSIX_sigpending          (__NR_POSIX + 265)
+#define __NR_POSIX_sigprocmask         (__NR_POSIX + 266)
+#define __NR_POSIX_sigsuspend          (__NR_POSIX + 267)
+#define __NR_POSIX_sigaction           (__NR_POSIX + 268)
+#define __NR_POSIX_MIPS_reserved1      (__NR_POSIX + 269)
+#define __NR_POSIX_MIPS_reserved2      (__NR_POSIX + 270)
+#define __NR_POSIX_MIPS_reserved3      (__NR_POSIX + 271)
+#define __NR_POSIX_MIPS_reserved4      (__NR_POSIX + 272)
+#define __NR_POSIX_MIPS_reserved5      (__NR_POSIX + 273)
+#define __NR_POSIX_MIPS_reserved6      (__NR_POSIX + 274)
+#define __NR_POSIX_MIPS_reserved7      (__NR_POSIX + 275)
+#define __NR_POSIX_MIPS_reserved8      (__NR_POSIX + 276)
+#define __NR_POSIX_MIPS_reserved9      (__NR_POSIX + 277)
+#define __NR_POSIX_MIPS_reserved10     (__NR_POSIX + 278)
+#define __NR_POSIX_MIPS_reserved11     (__NR_POSIX + 279)
+#define __NR_POSIX_TANDEM_reserved1    (__NR_POSIX + 280)
+#define __NR_POSIX_TANDEM_reserved2    (__NR_POSIX + 281)
+#define __NR_POSIX_TANDEM_reserved3    (__NR_POSIX + 282)
+#define __NR_POSIX_TANDEM_reserved4    (__NR_POSIX + 283)
+#define __NR_POSIX_TANDEM_reserved5    (__NR_POSIX + 284)
+#define __NR_POSIX_TANDEM_reserved6    (__NR_POSIX + 285)
+#define __NR_POSIX_TANDEM_reserved7    (__NR_POSIX + 286)
+#define __NR_POSIX_TANDEM_reserved8    (__NR_POSIX + 287)
+#define __NR_POSIX_TANDEM_reserved9    (__NR_POSIX + 288)
+#define __NR_POSIX_TANDEM_reserved10   (__NR_POSIX + 289)
+#define __NR_POSIX_TANDEM_reserved11   (__NR_POSIX + 290)
+#define __NR_POSIX_TANDEM_reserved12   (__NR_POSIX + 291)
+#define __NR_POSIX_TANDEM_reserved13   (__NR_POSIX + 292)
+#define __NR_POSIX_TANDEM_reserved14   (__NR_POSIX + 293)
+#define __NR_POSIX_TANDEM_reserved15   (__NR_POSIX + 294)
+#define __NR_POSIX_TANDEM_reserved16   (__NR_POSIX + 295)
+#define __NR_POSIX_TANDEM_reserved17   (__NR_POSIX + 296)
+#define __NR_POSIX_TANDEM_reserved18   (__NR_POSIX + 297)
+#define __NR_POSIX_TANDEM_reserved19   (__NR_POSIX + 298)
+#define __NR_POSIX_TANDEM_reserved20   (__NR_POSIX + 299)
+#define __NR_POSIX_SGI_reserved7       (__NR_POSIX + 300)
+#define __NR_POSIX_SGI_reserved8       (__NR_POSIX + 301)
+#define __NR_POSIX_SGI_reserved9       (__NR_POSIX + 302)
+#define __NR_POSIX_SGI_reserved10      (__NR_POSIX + 303)
+#define __NR_POSIX_SGI_reserved11      (__NR_POSIX + 304)
+#define __NR_POSIX_SGI_reserved12      (__NR_POSIX + 305)
+#define __NR_POSIX_SGI_reserved13      (__NR_POSIX + 306)
+#define __NR_POSIX_SGI_reserved14      (__NR_POSIX + 307)
+#define __NR_POSIX_SGI_reserved15      (__NR_POSIX + 308)
+#define __NR_POSIX_SGI_reserved16      (__NR_POSIX + 309)
+#define __NR_POSIX_SGI_reserved17      (__NR_POSIX + 310)
+#define __NR_POSIX_SGI_reserved18      (__NR_POSIX + 311)
+#define __NR_POSIX_SGI_reserved19      (__NR_POSIX + 312)
+#define __NR_POSIX_SGI_reserved20      (__NR_POSIX + 313)
+#define __NR_POSIX_SGI_reserved21      (__NR_POSIX + 314)
+#define __NR_POSIX_SGI_reserved22      (__NR_POSIX + 315)
+#define __NR_POSIX_SGI_reserved23      (__NR_POSIX + 316)
+#define __NR_POSIX_SGI_reserved24      (__NR_POSIX + 317)
+#define __NR_POSIX_SGI_reserved25      (__NR_POSIX + 318)
+#define __NR_POSIX_SGI_reserved26      (__NR_POSIX + 319)
+
+/*
+ * Linux syscalls are in the range from 4000 to 4999
+ * Hopefully these syscall numbers are unused ...  If not everyone using
+ * statically linked binaries is pretty upsh*t.  You've been warned.
+ */
+#define __NR_Linux                     4000
+#define __NR_syscall                   (__NR_Linux +   0)
+#define __NR_exit                      (__NR_Linux +   1)
+#define __NR_fork                      (__NR_Linux +   2)
+#define __NR_read                      (__NR_Linux +   3)
+#define __NR_write                     (__NR_Linux +   4)
+#define __NR_open                      (__NR_Linux +   5)
+#define __NR_close                     (__NR_Linux +   6)
+#define __NR_waitpid                   (__NR_Linux +   7)
+#define __NR_creat                     (__NR_Linux +   8)
+#define __NR_link                      (__NR_Linux +   9)
+#define __NR_unlink                    (__NR_Linux +  10)
+#define __NR_execve                    (__NR_Linux +  11)
+#define __NR_chdir                     (__NR_Linux +  12)
+#define __NR_time                      (__NR_Linux +  13)
+#define __NR_mknod                     (__NR_Linux +  14)
+#define __NR_chmod                     (__NR_Linux +  15)
+#define __NR_chown                     (__NR_Linux +  16)
+#define __NR_break                     (__NR_Linux +  17)
+#define __NR_oldstat                   (__NR_Linux +  18)
+#define __NR_lseek                     (__NR_Linux +  19)
+#define __NR_getpid                    (__NR_Linux +  20)
+#define __NR_mount                     (__NR_Linux +  21)
+#define __NR_umount                    (__NR_Linux +  22)
+#define __NR_setuid                    (__NR_Linux +  23)
+#define __NR_getuid                    (__NR_Linux +  24)
+#define __NR_stime                     (__NR_Linux +  25)
+#define __NR_ptrace                    (__NR_Linux +  26)
+#define __NR_alarm                     (__NR_Linux +  27)
+#define __NR_oldfstat                  (__NR_Linux +  28)
+#define __NR_pause                     (__NR_Linux +  29)
+#define __NR_utime                     (__NR_Linux +  30)
+#define __NR_stty                      (__NR_Linux +  31)
+#define __NR_gtty                      (__NR_Linux +  32)
+#define __NR_access                    (__NR_Linux +  33)
+#define __NR_nice                      (__NR_Linux +  34)
+#define __NR_ftime                     (__NR_Linux +  35)
+#define __NR_sync                      (__NR_Linux +  36)
+#define __NR_kill                      (__NR_Linux +  37)
+#define __NR_rename                    (__NR_Linux +  38)
+#define __NR_mkdir                     (__NR_Linux +  39)
+#define __NR_rmdir                     (__NR_Linux +  40)
+#define __NR_dup                       (__NR_Linux +  41)
+#define __NR_pipe                      (__NR_Linux +  42)
+#define __NR_times                     (__NR_Linux +  43)
+#define __NR_prof                      (__NR_Linux +  44)
+#define __NR_brk                       (__NR_Linux +  45)
+#define __NR_setgid                    (__NR_Linux +  46)
+#define __NR_getgid                    (__NR_Linux +  47)
+#define __NR_signal                    (__NR_Linux +  48)
+#define __NR_geteuid                   (__NR_Linux +  49)
+#define __NR_getegid                   (__NR_Linux +  50)
+#define __NR_acct                      (__NR_Linux +  51)
+#define __NR_phys                      (__NR_Linux +  52)
+#define __NR_lock                      (__NR_Linux +  53)
+#define __NR_ioctl                     (__NR_Linux +  54)
+#define __NR_fcntl                     (__NR_Linux +  55)
+#define __NR_mpx                       (__NR_Linux +  56)
+#define __NR_setpgid                   (__NR_Linux +  57)
+#define __NR_ulimit                    (__NR_Linux +  58)
+#define __NR_oldolduname               (__NR_Linux +  59)
+#define __NR_umask                     (__NR_Linux +  60)
+#define __NR_chroot                    (__NR_Linux +  61)
+#define __NR_ustat                     (__NR_Linux +  62)
+#define __NR_dup2                      (__NR_Linux +  63)
+#define __NR_getppid                   (__NR_Linux +  64)
+#define __NR_getpgrp                   (__NR_Linux +  65)
+#define __NR_setsid                    (__NR_Linux +  66)
+#define __NR_sigaction                 (__NR_Linux +  67)
+#define __NR_sgetmask                  (__NR_Linux +  68)
+#define __NR_ssetmask                  (__NR_Linux +  69)
+#define __NR_setreuid                  (__NR_Linux +  70)
+#define __NR_setregid                  (__NR_Linux +  71)
+#define __NR_sigsuspend                        (__NR_Linux +  72)
+#define __NR_sigpending                        (__NR_Linux +  73)
+#define __NR_sethostname               (__NR_Linux +  74)
+#define __NR_setrlimit                 (__NR_Linux +  75)
+#define __NR_getrlimit                 (__NR_Linux +  76)
+#define __NR_getrusage                 (__NR_Linux +  77)
+#define __NR_gettimeofday              (__NR_Linux +  78)
+#define __NR_settimeofday              (__NR_Linux +  79)
+#define __NR_getgroups                 (__NR_Linux +  80)
+#define __NR_setgroups                 (__NR_Linux +  81)
+#define __NR_select                    (__NR_Linux +  82)
+#define __NR_symlink                   (__NR_Linux +  83)
+#define __NR_oldlstat                  (__NR_Linux +  84)
+#define __NR_readlink                  (__NR_Linux +  85)
+#define __NR_uselib                    (__NR_Linux +  86)
+#define __NR_swapon                    (__NR_Linux +  87)
+#define __NR_reboot                    (__NR_Linux +  88)
+#define __NR_readdir                   (__NR_Linux +  89)
+#define __NR_mmap                      (__NR_Linux +  90)
+#define __NR_munmap                    (__NR_Linux +  91)
+#define __NR_truncate                  (__NR_Linux +  92)
+#define __NR_ftruncate                 (__NR_Linux +  93)
+#define __NR_fchmod                    (__NR_Linux +  94)
+#define __NR_fchown                    (__NR_Linux +  95)
+#define __NR_getpriority               (__NR_Linux +  96)
+#define __NR_setpriority               (__NR_Linux +  97)
+#define __NR_profil                    (__NR_Linux +  98)
+#define __NR_statfs                    (__NR_Linux +  99)
+#define __NR_fstatfs                   (__NR_Linux + 100)
+#define __NR_ioperm                    (__NR_Linux + 101)
+#define __NR_socketcall                        (__NR_Linux + 102)
+#define __NR_syslog                    (__NR_Linux + 103)
+#define __NR_setitimer                 (__NR_Linux + 104)
+#define __NR_getitimer                 (__NR_Linux + 105)
+#define __NR_stat                      (__NR_Linux + 106)
+#define __NR_lstat                     (__NR_Linux + 107)
+#define __NR_fstat                     (__NR_Linux + 108)
+#define __NR_olduname                  (__NR_Linux + 109)
+#define __NR_iopl                      (__NR_Linux + 110)
+#define __NR_vhangup                   (__NR_Linux + 111)
+#define __NR_idle                      (__NR_Linux + 112)
+#define __NR_vm86                      (__NR_Linux + 113)
+#define __NR_wait4                     (__NR_Linux + 114)
+#define __NR_swapoff                   (__NR_Linux + 115)
+#define __NR_sysinfo                   (__NR_Linux + 116)
+#define __NR_ipc                       (__NR_Linux + 117)
+#define __NR_fsync                     (__NR_Linux + 118)
+#define __NR_sigreturn                 (__NR_Linux + 119)
+#define __NR_clone                     (__NR_Linux + 120)
+#define __NR_setdomainname             (__NR_Linux + 121)
+#define __NR_uname                     (__NR_Linux + 122)
+#define __NR_modify_ldt                        (__NR_Linux + 123)
+#define __NR_adjtimex                  (__NR_Linux + 124)
+#define __NR_mprotect                  (__NR_Linux + 125)
+#define __NR_sigprocmask               (__NR_Linux + 126)
+#define __NR_create_module             (__NR_Linux + 127)
+#define __NR_init_module               (__NR_Linux + 128)
+#define __NR_delete_module             (__NR_Linux + 129)
+#define __NR_get_kernel_syms           (__NR_Linux + 130)
+#define __NR_quotactl                  (__NR_Linux + 131)
+#define __NR_getpgid                   (__NR_Linux + 132)
+#define __NR_fchdir                    (__NR_Linux + 133)
+#define __NR_bdflush                   (__NR_Linux + 134)
+#define __NR_sysfs                     (__NR_Linux + 135)
+#define __NR_personality               (__NR_Linux + 136)
+#define __NR_afs_syscall               (__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_setfsuid                  (__NR_Linux + 138)
+#define __NR_setfsgid                  (__NR_Linux + 139)
+#define __NR__llseek                   (__NR_Linux + 140)
+#define __NR_getdents                  (__NR_Linux + 141)
+#define __NR__newselect                        (__NR_Linux + 142)
+#define __NR_flock                     (__NR_Linux + 143)
+#define __NR_msync                     (__NR_Linux + 144)
+#define __NR_readv                     (__NR_Linux + 145)
+#define __NR_writev                    (__NR_Linux + 146)
+#define __NR_cacheflush                        (__NR_Linux + 147)
+#define __NR_cachectl                  (__NR_Linux + 148)
+#define __NR_sysmips                   (__NR_Linux + 149)
+#define __NR_setup                     (__NR_Linux + 150)      /* used only by init, to get system going */
+#define __NR_getsid                    (__NR_Linux + 151)
+#define __NR_reserved1                 (__NR_Linux + 152)
+#define __NR_reserved2                 (__NR_Linux + 153)
+#define __NR_mlock                     (__NR_Linux + 154)
+#define __NR_munlock                   (__NR_Linux + 155)
+#define __NR_mlockall                  (__NR_Linux + 156)
+#define __NR_munlockall                        (__NR_Linux + 157)
+
 
-#include <asm/mipsconfig.h>
 /*
- * Ugly kludge to enforce 32bit mode proof code.
- * Access errno via USEG, not KSEGx for internal kernel syscalls
+ * Offset of the last Linux flavoured syscall
  */
-#define errno (*(int *)((unsigned long)&errno - KERNELBASE))
+#define __NR_Linux_syscalls            157
 
-#endif /* __KERNEL__ */
+#ifndef __LANGUAGE_ASSEMBLY__
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
 type name(void) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name)); \
-if (__res >= 0) \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("li\t$2,%2\n\t" \
+                 "syscall" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name)); \
+if (__err == 0) \
        return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
+/*
+ * DANGER: This macro isn't usable for the pipe(2) call
+ * which has a unusual return convention.
+ */
 #define _syscall1(type,name,atype,a) \
 type name(atype a) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                 "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)) \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)) \
                   : "$4"); \
-if (__res >= 0) \
+if (__err == 0) \
        return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -45,16 +1193,18 @@ return -1; \
 type name(atype a,btype b) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                 "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
-                                      "r" ((long)(b))); \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)) \
                   : "$4","$5"); \
-if (__res >= 0) \
+if (__err == 0) \
        return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -62,18 +1212,20 @@ return -1; \
 type name (atype a, btype b, ctype c) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                 "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)) \
                   : "$4","$5","$6"); \
-if (__res>=0) \
+if (__err == 0) \
        return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -81,21 +1233,22 @@ return -1; \
 type name (atype a, btype b, ctype c, dtype d) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile (".set\tnoat\n\t" \
-                  "move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
-                  "move\t$7,%5\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                  "move\t$7,%6\n\t" \
+                 "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)) \
-                  : "$4","$5","$6","$7"); \
-if (__res>=0) \
+                  : "$4","$5","$6"); \
+if (__err == 0) \
        return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -103,24 +1256,105 @@ return -1; \
 type name (atype a,btype b,ctype c,dtype d,etype e) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile (".set\tnoat\n\t" \
-                  "move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
-                  "move\t$7,%5\n\t" \
-                  "move\t$3,%6\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                  "move\t$7,%6\n\t" \
+                  "move\t$3,%7\n\t" \
+                 "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)), \
                                       "r" ((long)(e)) \
-                  : "$3","$4","$5","$6","$7"); \
-if (__res>=0) \
+                  : "$3","$4","$5","$6"); \
+if (__err == 0) \
        return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * 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 _syscall2(int,clone,unsigned long,flags,char *,esp)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,setup)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+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 _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+
+static inline pid_t wait(int * wait_stat)
+{
+       return waitpid(-1,wait_stat,0);
+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+       long retval;
+
+       __asm__ __volatile__(
+               ".set\tnoreorder\n\t"
+               "move\t$8,$sp\n\t"
+               "move\t$4,%5\n\t"
+               "li\t$2,%1\n\t"
+               "syscall\n\t"
+               "beq\t$8,$sp,1f\n\t"
+               "subu\t$sp,16\n\t"      /* delay slot */
+               "jalr\t%4\n\t"
+               "move\t$4,%3\n\t"       /* delay slot */
+               "move\t$4,$2\n\t"
+               "li\t$2,%2\n\t"
+               "syscall\n"
+               "1:\taddiu\t$sp,16\n\t"
+               "move\t%0,$2\n\t"
+               ".set\treorder"
+               :"=r" (retval)
+               :"i" (__NR_clone), "i" (__NR_exit),
+                "r" (arg), "r" (fn),
+                "r" (flags | CLONE_VM)
+                /*
+                 * The called subroutine might have destroyed any of the
+                 * at, result, argument or temporary registers ...
+                 */
+               :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+                "$9","$10","$11","$12","$13","$14","$15","$24","$25");
+
+       return retval;
+}
+
+#endif /* !defined (__KERNEL_SYSCALLS__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
 #endif /* __ASM_MIPS_UNISTD_H */
diff --git a/include/asm-mips/user.h b/include/asm-mips/user.h
new file mode 100644 (file)
index 0000000..64069dd
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __ASM_MIPS_USER_H
+#define __ASM_MIPS_USER_H
+
+#include <linux/ptrace.h>
+
+#include <asm/page.h>
+#include <asm/reg.h>
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
+ * are as follows:
+ *
+ *  upage: 1 page consisting of a user struct that tells gdb
+ *     what is present in the file.  Directly after this is a
+ *     copy of the task_struct, which is currently not used by gdb,
+ *     but it may come in handy at some point.  All of the registers
+ *     are stored as part of the upage.  The upage should always be
+ *     only one page long.
+ *  data: The data segment follows next.  We use current->end_text to
+ *     current->brk to pick up all of the user variables, plus any memory
+ *     that may have been sbrk'ed.  No attempt is made to determine if a
+ *     page is demand-zero or if a page is totally unused, we just cover
+ *     the entire range.  All of the addresses are rounded in such a way
+ *     that an integral number of pages is written.
+ *  stack: We need the stack information in order to get a meaningful
+ *     backtrace.  We need to write the data from usp to
+ *     current->start_stack, so we round each of these in order to be able
+ *     to write an integer number of pages.
+ */
+struct user {
+       unsigned long   regs[EF_SIZE/8+32];     /* integer and fp regs */
+       size_t          u_tsize;                /* text size (pages) */
+       size_t          u_dsize;                /* data size (pages) */
+       size_t          u_ssize;                /* stack size (pages) */
+       unsigned long   start_code;             /* text starting address */
+       unsigned long   start_data;             /* data starting address */
+       unsigned long   start_stack;            /* stack starting address */
+       long int        signal;                 /* signal causing core dump */
+       struct regs *   u_ar0;                  /* help gdb find registers */
+       unsigned long   magic;                  /* identifies a core file */
+       char            u_comm[32];             /* user command name */
+};
+
+#define NBPG                   PAGE_SIZE
+#define UPAGES                 1
+#define HOST_TEXT_START_ADDR   (u.start_code)
+#define HOST_DATA_START_ADDR   (u.start_data)
+#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
+
+#endif /* __ASM_MIPS_USER_H */
diff --git a/include/asm-mips/vector.h b/include/asm-mips/vector.h
new file mode 100644 (file)
index 0000000..a7eed05
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * include/asm-mips/vector.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_VECTOR_H
+#define __ASM_MIPS_VECTOR_H
+
+/*
+ * This structure defines how to access various features of
+ * different machine types and how to access them.
+ *
+ * FIXME: More things need to be accessed via this vector.
+ */
+struct feature {
+       void (*handle_int)(void);
+       /*
+        * How to access the floppy controller's ports.
+        */
+       unsigned char (*fd_inb)(unsigned int port);
+       void (*fd_outb)(unsigned char value, unsigned int port);
+       /*
+        * How to access the floppy DMA functions.
+        */
+       void (*fd_enable_dma)(void);
+       void (*fd_disable_dma)(void);
+       int (*fd_request_dma)(void);
+       void (*fd_free_dma)(void);
+       void (*fd_clear_dma_ff)(void);
+       void (*fd_set_dma_mode)(char mode);
+       void (*fd_set_dma_addr)(unsigned int a);
+       void (*fd_set_dma_count)(unsigned int count);
+       int (*fd_get_dma_residue)(void);
+       void (*fd_enable_irq)(void);
+       void (*fd_disable_irq)(void);
+       void (*fd_cacheflush)(unsigned char *addr, unsigned int size);
+       /*
+        * How to access the RTC register of DS1287
+        */
+       unsigned char (*rtc_read_data)(void);
+       void (*rtc_write_data)(unsigned char);
+};
+
+/*
+ * Similar to the above this is a structure that describes various
+ * CPU dependend features.
+ *
+ * FIXME: This vector isn't being used yet
+ */
+struct cpu {
+       int dummy;      /* keep GCC from complaining */
+};
+
+extern struct feature *feature;
+extern struct cpu *cpu;
+
+#endif /* __ASM_MIPS_VECTOR_H */
index 69af8796114ba98e0a3af198e3a5d1e8b18e9f30..269f16b132142ecc382887cb084a35ac34ce0bf9 100644 (file)
@@ -33,6 +33,8 @@ enum machine_type {
 #endif
   /* skip a bunch so we don't run into any of sun's numbers */
   M_386 = 100,
+  M_MIPS1 = 151,       /* MIPS R3000/R3000 binary */
+  M_MIPS2 = 152,       /* MIPS R6000/R4000 binary */
 };
 
 #if !defined (N_MAGIC)
index c61b84ae3ad2953ae552455b1a354d606d1a353c..b3b56f5bedd239bbf2ee581ae1f2677ed59103f3 100644 (file)
@@ -78,11 +78,14 @@ extern int xd_init(void);
 #endif
 
 extern void set_device_ro(kdev_t dev,int flag);
+void add_blkdev_randomness(int major);
 
 extern int floppy_init(void);
 extern void rd_load(void);
-extern long rd_init(long mem_start, int length);
-extern int ramdisk_size;
+extern int rd_init(void);
+extern int rd_doload;          /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;     /* starting block # of image */
 
 #define RO_IOCTLS(dev,where) \
   case BLKROSET: if (!suser()) return -EACCES; \
@@ -102,14 +105,15 @@ extern int ramdisk_size;
 #define DEVICE_ON(device)      /* nothing */
 #define DEVICE_OFF(device)     /* nothing */
 
-#elif (MAJOR_NR == MEM_MAJOR)
+#elif (MAJOR_NR == RAMDISK_MAJOR)
 
 /* ram disk */
 #define DEVICE_NAME "ramdisk"
-#define DEVICE_REQUEST do_rd_request
-#define DEVICE_NR(device) (MINOR(device) & 7)
+#define DEVICE_REQUEST rd_request
+#define DEVICE_NR(device) (MINOR(device))
 #define DEVICE_ON(device) 
 #define DEVICE_OFF(device)
+#define DEVICE_NO_RANDOM
 
 #elif (MAJOR_NR == FLOPPY_MAJOR)
 
@@ -374,6 +378,9 @@ static void end_request(int uptodate) {
                        return;
                }
        }
+#ifndef DEVICE_NO_RANDOM
+       add_blkdev_randomness(MAJOR(req->rq_dev));
+#endif
 #ifdef IDE_DRIVER
        blk_dev[MAJOR(req->rq_dev)].current_request = req->next;
        hwgroup->rq = NULL;
index 7df4ee279fb6ca84ba72cab4d159b28897c14614..eb71550d30153bc29de64ab9487388af657c772e 100644 (file)
 
 /*--------- LOGITECH BUSMOUSE ITEMS -------------*/
 
+#define        LOGIBM_BASE             0x23c
 #define        MSE_DATA_PORT           0x23c
 #define        MSE_SIGNATURE_PORT      0x23d
 #define        MSE_CONTROL_PORT        0x23e
-#define MSE_INTERRUPT_PORT     0x23e
+#define        MSE_INTERRUPT_PORT      0x23e
 #define        MSE_CONFIG_PORT         0x23f
+#define        LOGIBM_EXTENT           0x4
 
 #define        MSE_ENABLE_INTERRUPTS   0x00
 #define        MSE_DISABLE_INTERRUPTS  0x10
 
 /*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
 
+#define        MSBM_BASE                       0x23d
 #define        MS_MSE_DATA_PORT                0x23d
 #define        MS_MSE_SIGNATURE_PORT           0x23e
 #define        MS_MSE_CONTROL_PORT             0x23c
 #define        MS_MSE_CONFIG_PORT              0x23f
+#define        MSBM_EXTENT                     0x3
 
 #define        MS_MSE_ENABLE_INTERRUPTS        0x11
 #define        MS_MSE_DISABLE_INTERRUPTS       0x10
index 87e285c0d119e636ab48e2dcfd6d27781d0f24c0..4c36b3c5bf56b2ac4c06ecf546841789e1c4b64e 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
 
-#include <asm/bitops.h>
-
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
  * that later. Anyway, now the file code is no longer dependent
 #define FIGETBSZ   _IO(0x00,2) /* get the block size used for bmap */
 
 #ifdef __KERNEL__
+
+#include <asm/bitops.h>
+
 extern void buffer_init(void);
 extern unsigned long inode_init(unsigned long start, unsigned long end);
 extern unsigned long file_table_init(unsigned long start, unsigned long end);
@@ -128,6 +129,7 @@ typedef char buffer_block[BLOCK_SIZE];
 #define BH_Req         3       /* 0 if the buffer has been invalidated */
 #define BH_Touched     4       /* 1 if the buffer has been touched (aging) */
 #define BH_Has_aged    5       /* 1 if the buffer has been aged (aging) */
+#define BH_Protected   6       /* 1 if the buffer is protected */
 
 struct buffer_head {
        char * b_data;                  /* pointer to data block (1024 bytes) */
@@ -180,6 +182,11 @@ static inline int buffer_has_aged(struct buffer_head * bh)
        return test_bit(BH_Has_aged, &bh->b_state);
 }
 
+static inline int buffer_protected(struct buffer_head * bh)
+{
+       return test_bit(BH_Protected, &bh->b_state);
+}
+
 #include <linux/pipe_fs_i.h>
 #include <linux/minix_fs_i.h>
 #include <linux/ext_fs_i.h>
index fe433fd4685114c1e4588758a4c129083b4ba8d4..c1b2dcf0c44f7276cebe8082d7295a6a43e244da 100644 (file)
@@ -55,6 +55,7 @@
 
 #define UNNAMED_MAJOR  0
 #define MEM_MAJOR      1
+#define RAMDISK_MAJOR  1
 #define FLOPPY_MAJOR   2
 #define PTY_MASTER_MAJOR 2
 #define IDE0_MAJOR     3
index 602025f9271b64edacbbc539b86805d0b4333336..c2e44397a1ecb0cc376353dd1929a02c531b9b08 100644 (file)
@@ -13,7 +13,7 @@
 
 struct vfsmount
 {
-   dev_t mnt_dev;                      /* Device this applies to */
+   kdev_t mnt_dev;                     /* Device this applies to */
    char *mnt_devname;                  /* Name of device e.g. /dev/dsk/hda1 */
    char *mnt_dirname;                  /* Name of directory mounted on */
    unsigned int mnt_flags;             /* Flags of this device */
@@ -25,6 +25,6 @@ struct vfsmount
    struct vfsmount *mnt_next;          /* pointer to next in linkedlist */
 };
 
-struct vfsmount *lookup_vfsmnt(dev_t dev);
+struct vfsmount *lookup_vfsmnt(kdev_t dev);
 
 #endif /* _LINUX_MOUNT_H */
index 68fcfe6d64ae6a3f2a60df897798726e7a3bbb26..a1539037e4a0ad2242606ebf7e1c21252185630a 100644 (file)
@@ -97,6 +97,16 @@ struct serial_multiport_struct {
        int     reserved[32];
 };
 
+/*
+ * Serial input interrupt line counters -- external structure
+ * Four lines can interrupt: CTS, DSR, RI, DCD
+ */
+struct serial_icounter_struct {
+       int cts, dsr, rng, dcd;
+       int reserved[16];
+};
+
+
 #ifdef __KERNEL__
 /*
  * This is our internal structure for each serial port's state.
@@ -110,6 +120,13 @@ struct serial_multiport_struct {
 #include <linux/termios.h>
 #include <linux/tqueue.h>
 
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+       __u32   cts, dsr, rng, dcd;     
+};
+
 struct async_struct {
        int                     magic;
        int                     baud_base;
@@ -148,6 +165,8 @@ struct async_struct {
        struct termios          callout_termios;
        struct wait_queue       *open_wait;
        struct wait_queue       *close_wait;
+       struct wait_queue       *delta_msr_wait;
+       struct async_icount     icount; /* kernel counters for the 4 input interrupts */
        struct async_struct     *next_port; /* For the linked list */
        struct async_struct     *prev_port;
 };
index 63dafb83394ea58403561861b866494ae8f40047..34ebf4dc006649549b3eb74fd193c10551d6d4dd 100644 (file)
@@ -49,7 +49,6 @@ extern void init_modules(void);
 extern long console_init(long, long);
 extern long kmalloc_init(long,long);
 extern void sock_init(void);
-extern long rd_init(long mem_start, int length);
 extern long pci_init(long, long);
 
 extern void swap_setup(char *str, int *ints);
@@ -102,7 +101,9 @@ extern void optcd_setup(char *str, int *ints);
 #ifdef CONFIG_SJCD
 extern void sjcd_setup(char *str, int *ints);
 #endif CONFIG_SJCD
-static void ramdisk_setup(char *str, int *ints);
+static void ramdisk_start_setup(char *str, int *ints);
+static void load_ramdisk(char *str, int *ints);
+static void prompt_ramdisk(char *str, int *ints);
 
 #ifdef CONFIG_SYSVIPC
 extern void ipc_init(void);
@@ -121,7 +122,9 @@ static unsigned long memory_end = 0;
 
 int rows, cols;
 
-int ramdisk_size;
+extern int rd_doload;          /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;     /* starting block # of image */
 int root_mountflags = MS_RDONLY;
 char *execute_command = 0;
 
@@ -173,7 +176,9 @@ struct {
 } bootsetups[] = {
        { "reserve=", reserve_setup },
        { "profile=", profile_setup },
-       { "ramdisk=", ramdisk_setup },
+       { "ramdisk_start=", ramdisk_start_setup },
+       { "load_ramdisk", load_ramdisk },
+       { "prompt_ramdisk", prompt_ramdisk },
        { "swap=", swap_setup },
        { "buff=", buff_setup },
 #ifdef CONFIG_BUGi386
@@ -268,10 +273,20 @@ struct {
        { 0, 0 }
 };
 
-static void ramdisk_setup(char *str, int *ints)
+static void ramdisk_start_setup(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
-      ramdisk_size = ints[1];
+      rd_image_start = ints[1];
+}
+
+static void load_ramdisk(char *str, int *ints)
+{
+       rd_doload = 1;
+}
+
+static void prompt_ramdisk(char *str, int *ints)
+{
+       rd_prompt = 1;
 }
 
 static int checksetup(char *line)
@@ -578,8 +593,6 @@ asmlinkage void start_kernel(void)
        memory_start = inode_init(memory_start,memory_end);
        memory_start = file_table_init(memory_start,memory_end);
        memory_start = name_cache_init(memory_start,memory_end);
-       if (ramdisk_size)
-               memory_start += rd_init(memory_start, ramdisk_size*1024);
        mem_init(memory_start,memory_end);
        buffer_init();
        sock_init();
index 2f39057ff62403cf89abe32d677d8f10ed1f91a8..37879e138dfa3e71e143b041cd1b55511b6e7aee 100644 (file)
@@ -96,7 +96,7 @@ void release(struct task_struct * p)
                        release_thread(p);
                        if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
                                printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm);
-                       free_page(p->kernel_stack_page);
+                       free_kernel_stack(p->kernel_stack_page);
                        current->cmin_flt += p->min_flt + p->cmin_flt;
                        current->cmaj_flt += p->maj_flt + p->cmaj_flt;
                        current->cnswap += p->nswap + p->cnswap;
@@ -446,7 +446,7 @@ static void exit_notify(void)
        /* 
         * Check to see if any process groups have become orphaned
         * as a result of our exiting, and if they have any stopped
-        * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
+        * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
         *
         * Case i: Our father is in a different pgrp than we are
         * and we were the only connection outside, so our pgrp
index 91710258ca0521eb2187e42bcee4208d55491ec6..354f90b259c851acefc1e783538f92d6a6a78bf6 100644 (file)
@@ -206,7 +206,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
        p = (struct task_struct *) kmalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
                goto bad_fork;
-       new_stack = get_free_page(GFP_KERNEL);
+       new_stack = alloc_kernel_stack();
        if (!new_stack)
                goto bad_fork_free_p;
        error = -EAGAIN;
@@ -285,7 +285,7 @@ bad_fork_cleanup:
        REMOVE_LINKS(p);
        nr_tasks--;
 bad_fork_free_stack:
-       free_page(new_stack);
+       free_kernel_stack(new_stack);
 bad_fork_free_p:
        kfree(p);
 bad_fork:
index 0e9e96e99defbbb8c6098a79e638be47e948215e..5557b811d3cf280f5d6446295c8be87dfaefa0d9 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
+#include <linux/kernel_stat.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
 #include <linux/ptrace.h>
@@ -342,6 +343,7 @@ struct symbol_table symbol_table = {
        X(do_gettimeofday),
        X(loops_per_sec),
        X(need_resched),
+       X(kstat),
        X(kill_proc),
        X(kill_pg),
        X(kill_sl),
@@ -473,6 +475,7 @@ struct symbol_table symbol_table = {
        X(scsi_init_malloc),
        X(scsi_init_free),
        X(scsi_ioctl),
+       X(scsi_mark_host_bus_reset),
        X(print_command),
        X(print_msg),
        X(print_status),
diff --git a/lib/inflate.c b/lib/inflate.c
new file mode 100644 (file)
index 0000000..94ce5b3
--- /dev/null
@@ -0,0 +1,1167 @@
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* 
+ * Adapted for booting Linux by Hannu Savolainen 1993
+ * based on gzip-1.0.3 
+ */
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor deals with some chunk of data at a time, and
+   decides which method to use on a chunk-by-chunk basis.  A chunk might
+   typically be 32K or 64K.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data is compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data is preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block codes up smaller that way (usually for quite small
+   chunks), otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block, and so
+   can code it much better than the pre-determined fixed codes.
+   The Huffman codes themselves are decoded using a mutli-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarly, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #";
+#endif
+
+#ifndef STATIC
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#  include <sys/types.h>
+#  include <stdlib.h>
+#endif
+
+#include "gzip.h"
+#define STATIC
+#endif /* !STATIC */
+       
+#define slide window
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft {
+  uch e;                /* number of extra bits or operation */
+  uch b;                /* number of bits in this code or subcode */
+  union {
+    ush n;              /* literal, length base, or distance base */
+    struct huft *t;     /* pointer to next level of table */
+  } v;
+};
+
+
+/* Function prototypes */
+STATIC int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+                   struct huft **, int *));
+STATIC int huft_free OF((struct huft *));
+STATIC int inflate_codes OF((struct huft *, struct huft *, int, int));
+STATIC int inflate_stored OF((void));
+STATIC int inflate_fixed OF((void));
+STATIC int inflate_dynamic OF((void));
+STATIC int inflate_block OF((int *));
+STATIC int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+/* unsigned wp;             current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = {    /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = {         /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static ush cpdext[] = {         /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+   
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the beginning of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes because fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+STATIC ulg bb;                         /* bit buffer */
+STATIC unsigned bk;                    /* bits in bit buffer */
+
+STATIC ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#define NEXTBYTE()  (uch)get_byte()
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+STATIC int lbits = 9;          /* bits in base literal/length lookup table */
+STATIC int dbits = 6;          /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16         /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+
+STATIC unsigned hufts;         /* track memory usage */
+
+
+STATIC int huft_build(b, n, s, d, e, t, m)
+unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
+unsigned n;             /* number of codes (assumed <= N_MAX) */
+unsigned s;             /* number of simple-valued codes (0..s-1) */
+ush *d;                 /* list of base values for non-simple codes */
+ush *e;                 /* list of extra bits for non-simple codes */
+struct huft **t;        /* result: starting table */
+int *m;                 /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  unsigned f;                   /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register unsigned i;          /* counter, current code */
+  register unsigned j;          /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  register unsigned *p;         /* pointer into c[], b[], or v[] */
+  register struct huft *q;      /* points to current table */
+  struct huft r;                /* table entry for structure assignment */
+  struct huft *u[BMAX];         /* table stack */
+  unsigned v[N_MAX];            /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  unsigned *xp;                 /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  unsigned z;                   /* number of entries in current table */
+
+DEBG("huft1 ");
+
+  /* Generate counts for each bit length */
+  memzero(c, sizeof(c));
+  p = b;  i = n;
+  do {
+    Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 
+           n-i, *p));
+    c[*p]++;                    /* assume all entries <= BMAX */
+    p++;                      /* Can't combine with above line (Solaris bug) */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (struct huft *)NULL;
+    *m = 0;
+    return 0;
+  }
+
+DEBG("huft2 ");
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)l > i)
+    l = i;
+  *m = l;
+
+DEBG("huft3 ");
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                 /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+DEBG("huft4 ");
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+DEBG("huft5 ");
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+
+DEBG("h6 ");
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+DEBG("h6a ");
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+DEBG("h6b ");
+    a = c[k];
+    while (a--)
+    {
+DEBG("h6b1 ");
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+DEBG1("1 ");
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+DEBG1("2 ");
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          while (++j < z)       /* try smaller tables up to z bits */
+          {
+            if ((f <<= 1) <= *++xp)
+              break;            /* enough codes to use up j bits */
+            f -= *xp;           /* else deduct codes from patterns */
+          }
+        }
+DEBG1("3 ");
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+            (struct huft *)NULL)
+        {
+          if (h)
+            huft_free(u[0]);
+          return 3;             /* not enough memory */
+        }
+DEBG1("4 ");
+        hufts += z + 1;         /* track memory usage */
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->v.t)) = (struct huft *)NULL;
+        u[h] = ++q;             /* table starts after link */
+
+DEBG1("5 ");
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l;         /* bits to dump before this table */
+          r.e = (uch)(16 + j);  /* bits in this table */
+          r.v.t = q;            /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+DEBG1("6 ");
+      }
+DEBG("h6c ");
+
+      /* set up table entry in r */
+      r.b = (uch)(k - w);
+      if (p >= v + n)
+        r.e = 99;               /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.e = (uch)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
+        r.v.n = (ush)(*p);             /* simple code is just the value */
+       p++;                           /* one compiler does not like *p++ */
+      }
+      else
+      {
+        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
+        r.v.n = d[*p++ - s];
+      }
+DEBG("h6d ");
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+DEBG("h6e ");
+    }
+DEBG("h6f ");
+  }
+
+DEBG("huft7 ");
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+
+STATIC int huft_free(t)
+struct huft *t;         /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *)NULL)
+  {
+    q = (--p)->v.t;
+    free((char*)p);
+    p = q;
+  } 
+  return 0;
+}
+
+
+STATIC int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td;   /* literal/length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  for (;;)                      /* do until end of block */
+  {
+    NEEDBITS((unsigned)bl)
+    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+      do {
+        if (e == 99)
+          return 1;
+        DUMPBITS(t->b)
+        e -= 16;
+        NEEDBITS(e)
+      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      slide[w++] = (uch)t->v.n;
+      Tracevv((stderr, "%c", slide[w-1]));
+      if (w == WSIZE)
+      {
+        flush_output(w);
+        w = 0;
+      }
+    }
+    else                        /* it's an EOB or a length */
+    {
+      /* exit if end of block */
+      if (e == 15)
+        break;
+
+      /* get length of block to copy */
+      NEEDBITS(e)
+      n = t->v.n + ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e);
+
+      /* decode distance of block to copy */
+      NEEDBITS((unsigned)bd)
+      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+      Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+      /* do the copy */
+      do {
+        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+        if (w - d >= e)         /* (this test assumes unsigned comparison) */
+        {
+          memcpy(slide + w, slide + d, e);
+          w += e;
+          d += e;
+        }
+        else                      /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+          do {
+            slide[w++] = slide[d++];
+           Tracevv((stderr, "%c", slide[w-1]));
+          } while (--e);
+        if (w == WSIZE)
+        {
+          flush_output(w);
+          w = 0;
+        }
+      } while (n);
+    }
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  /* done */
+  return 0;
+}
+
+
+
+STATIC int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+  unsigned n;           /* number of bytes in block */
+  unsigned w;           /* current window position */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<stor");
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+
+  /* go to byte boundary */
+  n = k & 7;
+  DUMPBITS(n);
+
+
+  /* get the length and its complement */
+  NEEDBITS(16)
+  n = ((unsigned)b & 0xffff);
+  DUMPBITS(16)
+  NEEDBITS(16)
+  if (n != (unsigned)((~b) & 0xffff))
+    return 1;                   /* error in compressed data */
+  DUMPBITS(16)
+
+
+  /* read and output the compressed data */
+  while (n--)
+  {
+    NEEDBITS(8)
+    slide[w++] = (uch)b;
+    if (w == WSIZE)
+    {
+      flush_output(w);
+      w = 0;
+    }
+    DUMPBITS(8)
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+STATIC int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+  int i;                /* temporary variable */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned l[288];      /* length list for huft_build */
+
+DEBG("<fix");
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)          /* make a complete, but wrong code set */
+    l[i] = 8;
+  bl = 7;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+    return i;
+
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+  {
+    huft_free(tl);
+
+    DEBG(">");
+    return i;
+  }
+
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+  return 0;
+}
+
+
+
+STATIC int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+  int i;                /* temporary variables */
+  unsigned j;
+  unsigned l;           /* last length */
+  unsigned m;           /* mask for bit lengths table */
+  unsigned n;           /* number of lengths to get */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned nb;          /* number of bit length codes */
+  unsigned nl;          /* number of literal/length codes */
+  unsigned nd;          /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+  unsigned ll[288+32];  /* literal/length and distance code lengths */
+#else
+  unsigned ll[286+30];  /* literal/length and distance code lengths */
+#endif
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<dyn");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in table lengths */
+  NEEDBITS(5)
+  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
+  DUMPBITS(5)
+  NEEDBITS(5)
+  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
+  DUMPBITS(5)
+  NEEDBITS(4)
+  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
+  DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+  if (nl > 288 || nd > 32)
+#else
+  if (nl > 286 || nd > 30)
+#endif
+    return 1;                   /* bad lengths */
+
+DEBG("dyn1 ");
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+  {
+    NEEDBITS(3)
+    ll[border[j]] = (unsigned)b & 7;
+    DUMPBITS(3)
+  }
+  for (; j < 19; j++)
+    ll[border[j]] = 0;
+
+DEBG("dyn2 ");
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+  {
+    if (i == 1)
+      huft_free(tl);
+    return i;                   /* incomplete code set */
+  }
+
+DEBG("dyn3 ");
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned)i < n)
+  {
+    NEEDBITS((unsigned)bl)
+    j = (td = tl + ((unsigned)b & m))->b;
+    DUMPBITS(j)
+    j = td->v.n;
+    if (j < 16)                 /* length of code in bits (0..15) */
+      ll[i++] = l = j;          /* save last length in l */
+    else if (j == 16)           /* repeat last length 3 to 6 times */
+    {
+      NEEDBITS(2)
+      j = 3 + ((unsigned)b & 3);
+      DUMPBITS(2)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = l;
+    }
+    else if (j == 17)           /* 3 to 10 zero length codes */
+    {
+      NEEDBITS(3)
+      j = 3 + ((unsigned)b & 7);
+      DUMPBITS(3)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+    else                        /* j == 18: 11 to 138 zero length codes */
+    {
+      NEEDBITS(7)
+      j = 11 + ((unsigned)b & 0x7f);
+      DUMPBITS(7)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+  }
+
+DEBG("dyn4 ");
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+DEBG("dyn5 ");
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+DEBG("dyn5a ");
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+  {
+DEBG("dyn5b ");
+    if (i == 1) {
+      error(" incomplete literal tree\n");
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+DEBG("dyn5c ");
+  bd = dbits;
+  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+  {
+DEBG("dyn5d ");
+    if (i == 1) {
+      error(" incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+      i = 0;
+    }
+#else
+      huft_free(td);
+    }
+    huft_free(tl);
+    return i;                   /* incomplete code set */
+#endif
+  }
+
+DEBG("dyn6 ");
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+DEBG("dyn7 ");
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+STATIC int inflate_block(e)
+int *e;                 /* last block flag */
+/* decompress an inflated block */
+{
+  unsigned t;           /* block type */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+  DEBG("<blk");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in last block bit */
+  NEEDBITS(1)
+  *e = (int)b & 1;
+  DUMPBITS(1)
+
+
+  /* read in block type */
+  NEEDBITS(2)
+  t = (unsigned)b & 3;
+  DUMPBITS(2)
+
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+  /* inflate that block type */
+  if (t == 2)
+    return inflate_dynamic();
+  if (t == 0)
+    return inflate_stored();
+  if (t == 1)
+    return inflate_fixed();
+
+  DEBG(">");
+
+  /* bad block type */
+  return 2;
+}
+
+
+
+STATIC int inflate()
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+  unsigned h;           /* maximum struct huft's malloc'ed */
+  void *ptr;
+
+  /* initialize window, bit buffer */
+  wp = 0;
+  bk = 0;
+  bb = 0;
+
+
+  /* decompress until the last block */
+  h = 0;
+  do {
+    hufts = 0;
+    gzip_mark(&ptr);
+    if ((r = inflate_block(&e)) != 0) {
+      gzip_release(&ptr);          
+      return r;
+    }
+    gzip_release(&ptr);
+    if (hufts > h)
+      h = hufts;
+  } while (!e);
+
+  /* Undo too much lookahead. The next read will be byte aligned so we
+   * can discard unused bits in the last meaningful byte.
+   */
+  while (bk >= 8) {
+    bk -= 8;
+    inptr--;
+  }
+
+  /* flush out slide */
+  flush_output(wp);
+
+
+  /* return success */
+#ifdef DEBUG
+  fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+  return 0;
+}
+
+/**********************************************************************
+ *
+ * The following are support routines for inflate.c
+ *
+ **********************************************************************/
+
+static ulg crc_32_tab[256];
+static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+#define CRC_VALUE (crc ^ 0xffffffffL)
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from 
+ * gzip-1.0.3/makecrc.c.
+ */
+
+static void
+makecrc(void)
+{
+/* Not copyrighted 1990 Mark Adler     */
+
+  unsigned long c;      /* crc shift register */
+  unsigned long e;      /* polynomial exclusive-or pattern */
+  int i;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+
+  /* terms of polynomial defining this crc (except x^32): */
+  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* Make exclusive-or pattern from polynomial */
+  e = 0;
+  for (i = 0; i < sizeof(p)/sizeof(int); i++)
+    e |= 1L << (31 - p[i]);
+
+  crc_32_tab[0] = 0;
+
+  for (i = 1; i < 256; i++)
+  {
+    c = 0;
+    for (k = i | 256; k != 1; k >>= 1)
+    {
+      c = c & 1 ? (c >> 1) ^ e : c >> 1;
+      if (k & 1)
+        c ^= e;
+    }
+    crc_32_tab[i] = c;
+  }
+}
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+/*
+ * Do the uncompression!
+ */
+static int gunzip(void)
+{
+    uch flags;
+    unsigned char magic[2]; /* magic header */
+    char method;
+    ulg orig_crc = 0;       /* original crc */
+    ulg orig_len = 0;       /* original uncompressed length */
+    int res;
+
+    magic[0] = (unsigned char)get_byte();
+    magic[1] = (unsigned char)get_byte();
+    method = (unsigned char)get_byte();
+
+    if (magic[0] != 037 ||
+       ((magic[1] != 0213) && (magic[1] != 0236))) {
+           error("bad gzip magic numbers");
+           return -1;
+    }
+
+    /* We only support method #8, DEFLATED */
+    if (method != 8)  {
+           error("internal error, invalid method");
+           return -1;
+    }
+
+    flags  = (uch)get_byte();
+    if ((flags & ENCRYPTED) != 0) {
+           error("Input is encrypted\n");
+           return -1;
+    }
+    if ((flags & CONTINUATION) != 0) {
+           error("Multi part input\n");
+           return -1;
+    }
+    if ((flags & RESERVED) != 0) {
+           error("Input has invalid flags\n");
+           return -1;
+    }
+    (ulg)get_byte();   /* Get timestamp */
+    ((ulg)get_byte()) << 8;
+    ((ulg)get_byte()) << 16;
+    ((ulg)get_byte()) << 24;
+
+    (void)get_byte();  /* Ignore extra flags for the moment */
+    (void)get_byte();  /* Ignore OS type for the moment */
+
+    if ((flags & EXTRA_FIELD) != 0) {
+           unsigned len = (unsigned)get_byte();
+           len |= ((unsigned)get_byte())<<8;
+           while (len--) (void)get_byte();
+    }
+
+    /* Get original file name if it was truncated */
+    if ((flags & ORIG_NAME) != 0) {
+           /* Discard the old name */
+           while (get_byte() != 0) /* null */ ;
+    } 
+
+    /* Discard file comment if any */
+    if ((flags & COMMENT) != 0) {
+           while (get_byte() != 0) /* null */ ;
+    }
+
+    /* Decompress */
+    if ((res = inflate())) {
+           switch (res) {
+           case 0:
+                   break;
+           case 1:
+                   error("invalid compressed format (err=1)");
+                   break;
+           case 2:
+                   error("invalid compressed format (err=2)");
+                   break;
+           case 3:
+                   error("out of memory");
+                   break;
+           default:
+                   error("invalid compressed format (other)");
+           }
+           return -1;
+    }
+           
+    /* Get the crc and original length */
+    /* crc32  (see algorithm.doc)
+     * uncompressed input size modulo 2^32
+     */
+    orig_crc = (ulg) get_byte();
+    orig_crc |= (ulg) get_byte() << 8;
+    orig_crc |= (ulg) get_byte() << 16;
+    orig_crc |= (ulg) get_byte() << 24;
+    
+    orig_len = (ulg) get_byte();
+    orig_len |= (ulg) get_byte() << 8;
+    orig_len |= (ulg) get_byte() << 16;
+    orig_len |= (ulg) get_byte() << 24;
+    
+    /* Validate decompression */
+    if (orig_crc != CRC_VALUE) {
+           error("crc error");
+           return -1;
+    }
+    if (orig_len != bytes_out) {
+           error("length error");
+           return -1;
+    }
+    return 0;
+}
+
+
index 9c66cc5fd479dcc807a9a532d0988419e5ca6f29..2c092f2434ceecd4899233764e9ffd5f71118180 100644 (file)
@@ -142,7 +142,7 @@ int filemap_swapout(struct vm_area_struct * vma,
 
        set_pte(page_table, __pte(entry));
        /* Yuck, perhaps a slightly modified swapout parameter set? */
-       invalidate_page(vma->vm_mm, (offset + vma->vm_start - vma->vm_offset));
+       invalidate_page(vma, (offset + vma->vm_start - vma->vm_offset));
        error = filemap_write_page(vma, offset, page);
        if (pte_val(*page_table) == entry)
                pte_clear(page_table);
@@ -180,14 +180,14 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
                if (!pte_dirty(pte))
                        return 0;
                set_pte(ptep, pte_mkclean(pte));
-               invalidate_page(vma->vm_mm, address);
+               invalidate_page(vma, address);
                page = pte_page(pte);
                mem_map[MAP_NR(page)].count++;
        } else {
                if (pte_none(pte))
                        return 0;
                pte_clear(ptep);
-               invalidate_page(vma->vm_mm, address);
+               invalidate_page(vma, address);
                if (!pte_present(pte)) {
                        swap_free(pte_val(pte));
                        return 0;
index 45e14adf8a683fc4e482bd18613aa0ee5129c05e..59470252bf746fd897e993b54048ebf258ff02b3 100644 (file)
@@ -59,7 +59,19 @@ int nr_free_pages = 0;
 struct mem_list free_area_list[NR_MEM_LISTS];
 unsigned char * free_area_map[NR_MEM_LISTS];
 
-#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE)
+/*
+ * We special-case the C-O-W ZERO_PAGE, because it's such
+ * a common occurrence (no need to read the page to know
+ * that it's zero - better for the cache and memory subsystem).
+ */
+static inline void copy_page(unsigned long from, unsigned long to)
+{
+       if (from == ZERO_PAGE) {
+               memset((void *) to, 0, PAGE_SIZE);
+               return;
+       }
+       memcpy((void *) to, (void *) from, PAGE_SIZE);
+}
 
 #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
 
@@ -549,8 +561,8 @@ unsigned long put_dirty_page(struct task_struct * tsk, unsigned long page, unsig
        }
        if (!pte_none(*pte)) {
                printk("put_dirty_page: page already exists\n");
-               pte_clear(pte);
-               invalidate_page(tsk->mm, address);
+               free_page(page);
+               return 0;
        }
        set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY))));
 /* no need for invalidate */
@@ -613,17 +625,17 @@ void do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma,
                        copy_page(old_page,new_page);
                        set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
                        free_page(old_page);
-                       invalidate_page(vma->vm_mm, address);
+                       invalidate_page(vma, address);
                        return;
                }
                set_pte(page_table, BAD_PAGE);
                free_page(old_page);
                oom(tsk);
-               invalidate_page(vma->vm_mm, address);
+               invalidate_page(vma, address);
                return;
        }
        set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
-       invalidate_page(vma->vm_mm, address);
+       invalidate_page(vma, address);
        if (new_page)
                free_page(new_page);
        return;
@@ -845,7 +857,7 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
                return 1;
 /* ok, need to mark it read-only, so invalidate any possible old TB entry */
        set_pte(from_table, pte_wrprotect(from));
-       invalidate_page(from_area->vm_mm, from_address);
+       invalidate_page(from_area, from_address);
        return 1;
 }
 
index b13d748d326f5161a08c58d9f32b57da2fa70be5..102d36cfc08a9115a028487dc4f0ebd456f37ae7 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -457,7 +457,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
                                return 0;
                        vma->vm_mm->rss--;
                        set_pte(page_table, __pte(entry));
-                       invalidate_page(vma->vm_mm, address);
+                       invalidate_page(vma, address);
                        tsk->nswap++;
                        write_swap_page(entry, (char *) page);
                }
@@ -472,13 +472,13 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
                }
                vma->vm_mm->rss--;
                set_pte(page_table, __pte(entry));
-               invalidate_page(vma->vm_mm, address);
+               invalidate_page(vma, address);
                free_page(page);
                return 1;
        } 
        vma->vm_mm->rss--;
        pte_clear(page_table);
-       invalidate_page(vma->vm_mm, address);
+       invalidate_page(vma, address);
        entry = mem_map[MAP_NR(page)].count;
        free_page(page);
        return entry;
index 46d4c33581c5308b4a10bb464e848a0869158a50..0c8440ccaaccd9632f4731a5f7deb102c2332e9b 100644 (file)
@@ -193,7 +193,7 @@ void netlink_detach(int unit)
 int netlink_post(int unit, struct sk_buff *skb)
 {
        unsigned long flags;
-       int ret=0;
+       int ret=-EUNATCH;
        if(open_map&(1<<unit))
        {
                save_flags(flags);