diff -u --recursive --new-file v1.3.47/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt --- v1.3.47/linux/Documentation/filesystems/hpfs.txt Sun Sep 3 12:26:47 1995 +++ linux/Documentation/filesystems/hpfs.txt Sun Dec 17 11:17:20 1995 @@ -9,10 +9,12 @@ 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. diff -u --recursive --new-file v1.3.47/linux/Makefile linux/Makefile --- v1.3.47/linux/Makefile Wed Dec 13 09:02:45 1995 +++ linux/Makefile Sun Dec 17 10:39:27 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 47 +SUBLEVEL = 48 ARCH = i386 @@ -171,11 +171,9 @@ 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 diff -u --recursive --new-file v1.3.47/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c --- v1.3.47/linux/arch/alpha/boot/main.c Sun Oct 29 11:38:47 1995 +++ linux/arch/alpha/boot/main.c Fri Dec 15 07:31:29 1995 @@ -229,7 +229,7 @@ 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"); diff -u --recursive --new-file v1.3.47/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v1.3.47/linux/arch/alpha/defconfig Sat Nov 25 19:04:35 1995 +++ linux/arch/alpha/defconfig Fri Dec 15 07:31:29 1995 @@ -40,7 +40,7 @@ # # 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 @@ # 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_MS_BUSMOUSE is not set # CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_QIC02_TAPE is not set +# CONFIG_APM is not set # # Sound diff -u --recursive --new-file v1.3.47/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v1.3.47/linux/arch/alpha/kernel/bios32.c Wed Nov 8 07:11:29 1995 +++ linux/arch/alpha/kernel/bios32.c Sun Dec 17 11:17:19 1995 @@ -427,6 +427,14 @@ 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 @@ 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 @@ /* 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 @@ PCI_INTERRUPT_LINE, dev->irq); #endif } + /* now, set any level-triggered IRQs */ + if (level_bits) + outb(level_bits, 0x4d1); + #if PCI_MODIFY { diff -u --recursive --new-file v1.3.47/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v1.3.47/linux/arch/alpha/kernel/setup.c Mon Nov 13 12:36:42 1995 +++ linux/arch/alpha/kernel/setup.c Fri Dec 15 07:31:30 1995 @@ -24,6 +24,7 @@ #include /* CONFIG_ALPHA_LCA etc */ #include +#include #include #include #include @@ -44,7 +45,7 @@ * 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 diff -u --recursive --new-file v1.3.47/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v1.3.47/linux/arch/alpha/mm/fault.c Tue Nov 21 13:22:05 1995 +++ linux/arch/alpha/mm/fault.c Thu Dec 14 20:15:35 1995 @@ -20,10 +20,6 @@ #include 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, diff -u --recursive --new-file v1.3.47/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v1.3.47/linux/arch/alpha/mm/init.c Sun Oct 29 11:38:48 1995 +++ linux/arch/alpha/mm/init.c Fri Dec 15 07:31:30 1995 @@ -50,12 +50,6 @@ 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 @@ /* 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); diff -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v1.3.47/linux/arch/i386/boot/compressed/Makefile Fri Nov 17 08:42:24 1995 +++ linux/arch/i386/boot/compressed/Makefile Thu Dec 14 08:16:53 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/Makefile.debug linux/arch/i386/boot/compressed/Makefile.debug --- v1.3.47/linux/arch/i386/boot/compressed/Makefile.debug Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/Makefile.debug Thu Dec 14 08:16:52 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/crypt.h linux/arch/i386/boot/compressed/crypt.h --- v1.3.47/linux/arch/i386/boot/compressed/crypt.h Thu Dec 29 19:58:41 1994 +++ linux/arch/i386/boot/compressed/crypt.h Thu Jan 1 02:00:00 1970 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/gzip.h linux/arch/i386/boot/compressed/gzip.h --- v1.3.47/linux/arch/i386/boot/compressed/gzip.h Thu Dec 29 19:58:41 1994 +++ linux/arch/i386/boot/compressed/gzip.h Thu Jan 1 02:00:00 1970 @@ -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 -# define memzero(s, n) memset ((s), 0, (n)) -#else -# include -# 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 -#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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/inflate.c linux/arch/i386/boot/compressed/inflate.c --- v1.3.47/linux/arch/i386/boot/compressed/inflate.c Thu Dec 29 19:58:41 1994 +++ linux/arch/i386/boot/compressed/inflate.c Thu Jan 1 02:00:00 1970 @@ -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 -# include -#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())<>=(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(""); - 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(" 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(" 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(""); - - /* 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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/lzw.h linux/arch/i386/boot/compressed/lzw.h --- v1.3.47/linux/arch/i386/boot/compressed/lzw.h Thu Dec 29 19:58:41 1994 +++ linux/arch/i386/boot/compressed/lzw.h Thu Jan 1 02:00:00 1970 @@ -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)); diff -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v1.3.47/linux/arch/i386/boot/compressed/misc.c Tue Nov 21 13:22:05 1995 +++ linux/arch/i386/boot/compressed/misc.c Thu Dec 14 08:16:53 1995 @@ -8,13 +8,69 @@ * puts by Nick Holloway 1993, better puts by Martin Mares 1995 */ -#include "gzip.h" -#include "lzw.h" +#include #include #include /* + * 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 @@ #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; +static long free_mem_ptr = (long)&end; -int to_stdout = 0; -int hard_math = 0; +static char *vidmem = (char *)0xb8000; +static int vidport; +static int lines, cols; -void (*work)(int inf, int outf); -void makecrc(void); +#include "../../../../lib/inflate.c" -local int get_method(int); - -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"); + if (free_mem_ptr >= 0x90000) + error("\nOut of memory\n"); - return p; - } - if (free_mem_ptr < 0x90000) 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 @@ 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> 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 @@ 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 @@ 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..."); - - method = get_method(0); - - work(0, 0); - - puts("done.\n"); - - puts("Now booting the kernel\n"); + gunzip(); + puts("done.\nNow booting the kernel\n"); } +#endif -/* ======================================================================== - * 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 -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/unzip.c linux/arch/i386/boot/compressed/unzip.c --- v1.3.47/linux/arch/i386/boot/compressed/unzip.c Thu Dec 29 19:58:41 1994 +++ linux/arch/i386/boot/compressed/unzip.c Thu Jan 1 02:00:00 1970 @@ -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 - -/* 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 */ -} diff -u --recursive --new-file v1.3.47/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v1.3.47/linux/arch/i386/kernel/setup.c Mon Dec 11 15:42:00 1995 +++ linux/arch/i386/kernel/setup.c Thu Dec 14 08:16:53 1995 @@ -62,7 +62,9 @@ #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 @@ #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 @@ 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; diff -u --recursive --new-file v1.3.47/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v1.3.47/linux/arch/mips/Makefile Tue Aug 15 20:39:00 1995 +++ linux/arch/mips/Makefile Wed Dec 13 12:39:42 1995 @@ -10,38 +10,84 @@ # 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 @@ archclean: @$(MAKEBOOT) clean + $(MAKE) -C arch/$(ARCH)/kernel clean archdep: @$(MAKEBOOT) dep diff -u --recursive --new-file v1.3.47/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v1.3.47/linux/arch/mips/boot/Makefile Tue Jan 17 00:57:01 1995 +++ linux/arch/mips/boot/Makefile Wed Dec 13 12:39:42 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/config.in linux/arch/mips/config.in --- v1.3.47/linux/arch/mips/config.in Tue Aug 8 12:31:33 1995 +++ linux/arch/mips/config.in Wed Dec 13 12:39:43 1995 @@ -2,255 +2,107 @@ # 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 '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 -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 +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 +tristate 'SCSI support' CONFIG_SCSI -if [ "$CONFIG_SCSI" = "n" ]; then - -comment 'Skipping SCSI configuration options...' - -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' +mainmenu_option next_comment +comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)' -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' - -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 -u --recursive --new-file v1.3.47/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v1.3.47/linux/arch/mips/defconfig Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/defconfig Wed Dec 13 12:39:43 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v1.3.47/linux/arch/mips/kernel/Makefile Tue Aug 15 20:39:00 1995 +++ linux/arch/mips/kernel/Makefile Wed Dec 13 12:39:43 1995 @@ -1,53 +1,101 @@ # -# 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 -cache.o: cache.s +# +# 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 + +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 + +ifdef CONFIG_CPU_R3000 +O_OBJS += r3000.o +endif + +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 -entry.o: entry.s +# +# 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)) -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 +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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/cache.S linux/arch/mips/kernel/cache.S --- v1.3.47/linux/arch/mips/kernel/cache.S Fri Jan 13 20:27:37 1995 +++ linux/arch/mips/kernel/cache.S Thu Jan 1 02:00:00 1970 @@ -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 -#include -#include - -#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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v1.3.47/linux/arch/mips/kernel/entry.S Wed Jan 25 08:54:22 1995 +++ linux/arch/mips/kernel/entry.S Wed Dec 13 12:39:43 1995 @@ -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/.S */ - #include -#include + +#include +#include #include #include #include #include +#include #include -#include #include +#include /* * These are offsets into the task-struct. @@ -30,944 +36,276 @@ 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 - - lw t0,errno(s0) - sw v0,FR_REG2(sp) # save the return value - subu t0,zero,t0 - beqz t0,1f - nop # delay slot - sw t1,FR_REG2(sp) - /* - * Fixme: should set error flag - */ -1: jal _syscall_trace - nop + 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 + +reschedule: jal schedule + nop # delay slot +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 - .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 +EXPORT(return) RESTORE_ALL + ERET .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: - .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 +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 - .globl _handle_vcei - .align 5 -_handle_vcei: + .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 +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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v1.3.47/linux/arch/mips/kernel/gdb-low.S Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/gdb-low.S Wed Dec 13 12:39:43 1995 @@ -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 + +#include +#include +#include +#include +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v1.3.47/linux/arch/mips/kernel/gdb-stub.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/gdb-stub.c Wed Dec 13 12:39:43 1995 @@ -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 + * + * 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 + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * 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 $# + */ +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; + + /* + * $#. + */ + + 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; itt && 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 *)®s->cp0_epc, ptr, 4, 0); + *ptr++ = ';'; + + /* + * Send frame pointer + */ + *ptr++ = hexchars[REG_FP >> 4]; + *ptr++ = hexchars[REG_FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®s->reg30, ptr, 4, 0); + *ptr++ = ';'; + + /* + * Send stack pointer + */ + *ptr++ = hexchars[REG_SP >> 4]; + *ptr++ = hexchars[REG_SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®s->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 *)®s->reg0, ptr, 32*4, 0); /* r0...r31 */ + ptr = mem2hex((char *)®s->cp0_status, ptr, 6*4, 0); /* cp0 */ + ptr = mem2hex((char *)®s->fpr0, ptr, 32*4, 0); /* f0...31 */ + ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*4, 0); /* cp1 */ + ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*4, 0); /* frp */ + ptr = mem2hex((char *)®s->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); +} diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v1.3.47/linux/arch/mips/kernel/head.S Tue Jan 31 09:39:02 1995 +++ linux/arch/mips/kernel/head.S Wed Dec 13 12:39:43 1995 @@ -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 +#include #include #include #include #include #include -#include #include -#include #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 @@ */ .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 @@ * 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 - */ - .set reorder - jal setup_paging -#if KERNELBASE == KSEG0 - jal _sys_cacheflush -#endif + * 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. + */ + 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 + + /* + * 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 +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 @@ 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 @@ 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 -#include -#include - -#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 @@ * 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 +MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache +MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space - .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 - -# 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... - - .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 (???) +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 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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ioport.c linux/arch/mips/kernel/ioport.c --- v1.3.47/linux/arch/mips/kernel/ioport.c Wed Jan 18 08:54:13 1995 +++ linux/arch/mips/kernel/ioport.c Wed Dec 13 12:39:43 1995 @@ -7,50 +7,8 @@ #include #include -#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) { @@ -75,29 +33,4 @@ long eip,long cs,long eflags,long esp,long ss) { 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c --- v1.3.47/linux/arch/mips/kernel/ipc.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/ipc.c Wed Dec 13 12:39:43 1995 @@ -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 +#include +#include +#include +#include +#include +#include + +#include + +/* + * 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 */ +} diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v1.3.47/linux/arch/mips/kernel/irq.c Tue Jan 31 09:39:02 1995 +++ linux/arch/mips/kernel/irq.c Wed Dec 13 12:39:43 1995 @@ -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 @@ -27,13 +29,18 @@ #include #include #include +#include #include #include +#include -#include +#include +#include #include #include -#include +#include +#include +#include unsigned char cache_21 = 0xff; unsigned char cache_A1 = 0xff; @@ -117,7 +124,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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<handler = NULL; action->flags = 0; action->mask = 0; @@ -228,7 +241,7 @@ 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 @@ return irqs; } -int probe_irq_off (unsigned int irqs) +int probe_irq_off (unsigned long irqs) { unsigned int i, irqmask; @@ -284,14 +297,35 @@ { 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/jazz-c.c linux/arch/mips/kernel/jazz-c.c --- v1.3.47/linux/arch/mips/kernel/jazz-c.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/jazz-c.c Wed Dec 13 12:39:43 1995 @@ -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 + +#include +#include +#include +#include + +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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/jazzdma.c linux/arch/mips/kernel/jazzdma.c --- v1.3.47/linux/arch/mips/kernel/jazzdma.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/jazzdma.c Wed Dec 13 12:39:43 1995 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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 1) + printk("vdma_alloc: Allocated %d pages starting from %08lx\n", + pages,laddr); + + if (vdma_debug > 2) + { + printk("LADDR: "); + for (i=first; i> 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> 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 +#include +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/pica.S linux/arch/mips/kernel/pica.S --- v1.3.47/linux/arch/mips/kernel/pica.S Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/pica.S Wed Dec 13 12:39:43 1995 @@ -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 +#include +#include +#include +#include + +/* + * 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) + diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v1.3.47/linux/arch/mips/kernel/process.c Fri Oct 6 14:35:15 1995 +++ linux/arch/mips/kernel/process.c Wed Dec 13 12:39:43 1995 @@ -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 #include #include @@ -18,54 +15,80 @@ #include #include #include +#include +#include #include #include +#include #include +#include #include #include -#include +#include #include +#include -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 @@ * 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,¤t->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, ®s); - putname(filename); - return error; + /* + * To do... + */ } diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v1.3.47/linux/arch/mips/kernel/ptrace.c Thu Sep 7 17:17:16 1995 +++ linux/arch/mips/kernel/ptrace.c Wed Dec 13 12:39:44 1995 @@ -11,6 +11,7 @@ #include #include +#include #include #if 0 @@ -150,10 +151,8 @@ 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 @@ 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/r4xx0.S linux/arch/mips/kernel/r4xx0.S --- v1.3.47/linux/arch/mips/kernel/r4xx0.S Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/r4xx0.S Wed Dec 13 12:39:44 1995 @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/resume.S linux/arch/mips/kernel/resume.S --- v1.3.47/linux/arch/mips/kernel/resume.S Wed Jan 25 08:54:22 1995 +++ linux/arch/mips/kernel/resume.S Thu Jan 1 02:00:00 1970 @@ -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 -#include -#include -#include - -/* - * 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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v1.3.47/linux/arch/mips/kernel/setup.c Mon Sep 18 14:53:48 1995 +++ linux/arch/mips/kernel/setup.c Wed Dec 13 12:39:44 1995 @@ -2,13 +2,16 @@ * linux/arch/mips/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 1995 Ralf Baechle */ - +#include +#include #include #include #include #include #include +#include #include #include #include @@ -17,11 +20,164 @@ #include #include +#include #include +#include #include +#include #include /* + * 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.. */ char wait_available; /* set if the "wait" instruction available */ @@ -35,12 +191,12 @@ * 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 @@ * 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 */ diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v1.3.47/linux/arch/mips/kernel/signal.c Mon Jan 23 23:04:08 1995 +++ linux/arch/mips/kernel/signal.c Wed Dec 13 12:39:44 1995 @@ -3,7 +3,6 @@ * * Copyright (C) 1991, 1992 Linus Torvalds */ - #include #include #include @@ -13,6 +12,7 @@ #include #include +#include #include #include @@ -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 @@ /* * 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); + frame--; + /* - * set up the "normal" stack seen by the signal handler + * 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->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); - /* - * Don't copy k0/k1 - */ - 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->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 */ - sys_cacheflush(frame, 32*4, BCACHE); + 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 @@ { 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, ¤t->signal); + sa = current->sig->action + signr; signr++; if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; @@ -219,7 +265,7 @@ 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 @@ 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 @@ 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v1.3.47/linux/arch/mips/kernel/syscall.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/syscall.c Wed Dec 13 12:39:44 1995 @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v1.3.47/linux/arch/mips/kernel/syscalls.h Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/syscalls.h Wed Dec 13 12:39:44 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v1.3.47/linux/arch/mips/kernel/sysmips.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/sysmips.c Wed Dec 13 12:39:44 1995 @@ -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 +#include +#include +#include +#include +#include + +#include +#include +#include + +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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v1.3.47/linux/arch/mips/kernel/time.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/time.c Wed Dec 13 12:39:44 1995 @@ -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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tlb.S linux/arch/mips/kernel/tlb.S --- v1.3.47/linux/arch/mips/kernel/tlb.S Fri Jan 13 23:49:20 1995 +++ linux/arch/mips/kernel/tlb.S Thu Jan 1 02:00:00 1970 @@ -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 -#include -#include - - .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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v1.3.47/linux/arch/mips/kernel/traps.c Tue Jun 27 14:11:30 1995 +++ linux/arch/mips/kernel/traps.c Wed Dec 13 12:39:44 1995 @@ -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. */ /* @@ -9,17 +11,23 @@ * 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 #include #include #include #include +#include #include #include -#include #include +#include +#include +#include +#include #include #include #include @@ -32,18 +40,15 @@ 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_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 @@ * 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; ipid >= 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; ipid >= 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_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 @@ { /* * 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 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 @@ * 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 @@ 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 @@ 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tyne-c.c linux/arch/mips/kernel/tyne-c.c --- v1.3.47/linux/arch/mips/kernel/tyne-c.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/tyne-c.c Wed Dec 13 12:39:44 1995 @@ -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 +#include +#include +#include +#include +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tyne.S linux/arch/mips/kernel/tyne.S --- v1.3.47/linux/arch/mips/kernel/tyne.S Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/kernel/tyne.S Wed Dec 13 12:39:44 1995 @@ -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 +#include +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tynedma.c linux/arch/mips/kernel/tynedma.c --- v1.3.47/linux/arch/mips/kernel/tynedma.c Wed Jan 25 08:54:22 1995 +++ linux/arch/mips/kernel/tynedma.c Thu Jan 1 02:00:00 1970 @@ -1,35 +0,0 @@ -/* - * Tiny Tyne DMA buffer allocator - * - * Copyright (C) 1995 Ralf Baechle - */ -#include -#include -#include - -#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 -u --recursive --new-file v1.3.47/linux/arch/mips/ld.script linux/arch/mips/ld.script --- v1.3.47/linux/arch/mips/ld.script Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/ld.script Wed Dec 13 12:39:44 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v1.3.47/linux/arch/mips/lib/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/lib/Makefile Wed Dec 13 12:39:44 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c --- v1.3.47/linux/arch/mips/lib/checksum.c Thu Jan 1 02:00:00 1970 +++ linux/arch/mips/lib/checksum.c Wed Dec 13 12:39:44 1995 @@ -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, + * 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 +#include + +/* + * 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; +} diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v1.3.47/linux/arch/mips/mm/Makefile Tue Aug 15 20:39:00 1995 +++ linux/arch/mips/mm/Makefile Wed Dec 13 12:39:44 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v1.3.47/linux/arch/mips/mm/fault.c Wed Jan 25 08:54:22 1995 +++ linux/arch/mips/mm/fault.c Wed Dec 13 12:39:44 1995 @@ -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 #include #include #include @@ -19,7 +16,7 @@ #include #include -#include +#include extern void die_if_kernel(char *, struct pt_regs *, long); @@ -27,61 +24,43 @@ * 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 @@ 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 @@ * 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); } diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v1.3.47/linux/arch/mips/mm/init.c Sun Sep 3 12:26:49 1995 +++ linux/arch/mips/mm/init.c Wed Dec 13 12:39:45 1995 @@ -4,7 +4,6 @@ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * Ported to MIPS by Ralf Baechle */ - #include #include #include @@ -17,11 +16,12 @@ #include #include +#include +#include +#include #include #include -#include - -extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ +#include extern void deskstation_tyne_dma_init(void); extern void scsi_mem_init(unsigned long); @@ -29,6 +29,8 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ #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 @@ 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; diff -u --recursive --new-file v1.3.47/linux/drivers/Makefile linux/drivers/Makefile --- v1.3.47/linux/drivers/Makefile Mon Oct 23 18:02:01 1995 +++ linux/drivers/Makefile Thu Dec 14 16:02:24 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v1.3.47/linux/drivers/block/Makefile Mon Dec 11 15:42:00 1995 +++ linux/drivers/block/Makefile Thu Dec 14 08:16:53 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/drivers/block/README.ide linux/drivers/block/README.ide --- v1.3.47/linux/drivers/block/README.ide Mon Dec 11 15:42:00 1995 +++ linux/drivers/block/README.ide Sun Dec 17 11:17:19 1995 @@ -12,6 +12,8 @@ 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) diff -u --recursive --new-file v1.3.47/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c --- v1.3.47/linux/drivers/block/cmd640.c Mon Dec 11 15:42:00 1995 +++ linux/drivers/block/cmd640.c Sun Dec 17 11:17:19 1995 @@ -237,7 +237,7 @@ { 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 @@ */ 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 @@ 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 @@ */ 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 @@ 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; diff -u --recursive --new-file v1.3.47/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v1.3.47/linux/drivers/block/genhd.c Mon Nov 27 12:48:28 1995 +++ linux/drivers/block/genhd.c Thu Dec 14 08:16:53 1995 @@ -30,7 +30,6 @@ 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 @@ nr += p->nr_real; } - if (ramdisk_size) - rd_load(); + rd_load(); } diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v1.3.47/linux/drivers/block/ide-tape.c Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/ide-tape.c Sun Dec 17 11:17:19 1995 @@ -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 * @@ -17,14 +17,15 @@ * 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: * @@ -34,19 +35,15 @@ * 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. * @@ -86,14 +83,14 @@ * 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. @@ -118,6 +115,26 @@ * 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: @@ -135,6 +152,72 @@ * */ +/* + * 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 #include #include @@ -161,7 +244,7 @@ /* * 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" @@ -214,6 +297,8 @@ * */ +#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 @@ -242,6 +327,15 @@ #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_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 @@ */ 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,11 +825,24 @@ * 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_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 @@ 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 @@ 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 @@ 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 @@ /* * 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 @@ 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 @@ #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 @@ 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;icurrent_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 @@ #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 @@ 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 @@ { 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_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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) 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 @@ 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 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. + */ - 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); + 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 */ } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); + + /* + * 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)); } - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; + rq=&(new_stage->rq); + + 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); + + 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 @@ /* * 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 @@ /* * 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 @@ 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 @@ 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 @@ { 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 @@ drive=idetape_chrdev.drive; tape=&(drive->tape); + tape->last_dt_was_write=1; if (count==0) @@ -2924,26 +3252,25 @@ 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 @@ 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 @@ #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 @@ 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 @@ } tape->last_dt_was_write=0; - + return (0); } @@ -3225,6 +3554,8 @@ 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 @@ } } - save_flags (flags); - cli(); + save_flags (flags);cli(); tape->busy=0; restore_flags (flags); - + return; } @@ -3310,4 +3640,315 @@ pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE; 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;inext=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); } diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide-tape.h linux/drivers/block/ide-tape.h --- v1.3.47/linux/drivers/block/ide-tape.h Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/ide-tape.h Sun Dec 17 11:17:19 1995 @@ -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 */ @@ -19,6 +19,63 @@ /**************************** 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: * * 1. Generally log all driver actions. @@ -45,15 +102,6 @@ #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 * commands (Not for READ/WRITE commands). @@ -80,70 +128,56 @@ * 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 -/* - * 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. - * - * 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. - * - * 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. +#define IDETAPE_PC_STACK 20+IDETAPE_MAX_PC_RETRIES + +/* + * 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. + * + * The polling frequency is 1/IDETAPE_DSC_READ_WRITE_FREQUENCY, + * and it should be relatively fast. The default is a period + * of 50 msec. + * + * 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 ***********************/ @@ -226,6 +260,30 @@ } 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 * of type tape_info, defined below. @@ -268,9 +326,9 @@ * 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 @@ /* * 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 @@ /* 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 */ diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v1.3.47/linux/drivers/block/ide.c Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/ide.c Sun Dec 17 11:17:19 1995 @@ -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) */ @@ -178,6 +178,7 @@ * 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 * @@ -187,6 +188,7 @@ * - 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 @@ 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 @@ static byte current_select = 0; if (hwif->select != current_select) { + byte t; unsigned long flags; save_flags (flags); cli(); @@ -422,8 +427,16 @@ (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 @@ } 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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ || (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 @@ /* * 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 @@ 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->bios_cyl; - drive->head = drive->bios_head; - drive->sect = drive->bios_sect; + drive->cyl = drive->id->cyls; + drive->head = drive->id->heads; + drive->sect = drive->id->sectors; + } + 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; diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v1.3.47/linux/drivers/block/ide.h Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/ide.h Sun Dec 17 11:17:19 1995 @@ -355,6 +355,9 @@ 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; /* @@ -413,6 +416,14 @@ 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 * of the "bad" bits, and if all is okay it returns 0. All other @@ -443,7 +454,8 @@ 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 @@ * 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); @@ -534,6 +552,13 @@ */ 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 */ diff -u --recursive --new-file v1.3.47/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v1.3.47/linux/drivers/block/ll_rw_blk.c Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/ll_rw_blk.c Thu Dec 14 08:16:53 1995 @@ -623,6 +623,7 @@ 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 -u --recursive --new-file v1.3.47/linux/drivers/block/ramdisk.c linux/drivers/block/ramdisk.c --- v1.3.47/linux/drivers/block/ramdisk.c Mon Oct 23 18:02:03 1995 +++ linux/drivers/block/ramdisk.c Thu Jan 1 02:00:00 1970 @@ -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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MAJOR_NR MEM_MAJOR -#include - -#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 -u --recursive --new-file v1.3.47/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v1.3.47/linux/drivers/block/rd.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/block/rd.c Thu Dec 14 08:29:23 1995 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 + +#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 + +/* + * 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 + + + diff -u --recursive --new-file v1.3.47/linux/drivers/block/triton.c linux/drivers/block/triton.c --- v1.3.47/linux/drivers/block/triton.c Mon Dec 11 15:42:01 1995 +++ linux/drivers/block/triton.c Sun Dec 17 11:17:19 1995 @@ -71,6 +71,20 @@ * - 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. * diff -u --recursive --new-file v1.3.47/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- v1.3.47/linux/drivers/cdrom/cdu31a.c Mon Nov 27 12:48:29 1995 +++ linux/drivers/cdrom/cdu31a.c Thu Dec 14 16:24:58 1995 @@ -170,7 +170,6 @@ */ #include -#include #include diff -u --recursive --new-file v1.3.47/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c --- v1.3.47/linux/drivers/cdrom/sbpcd.c Tue Nov 21 13:22:09 1995 +++ linux/drivers/cdrom/sbpcd.c Thu Dec 14 16:25:43 1995 @@ -285,6 +285,7 @@ #include #include #include +#include #if !(SBPCD_ISSUE-1) #define MAJOR_NR MATSUSHITA_CDROM_MAJOR diff -u --recursive --new-file v1.3.47/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v1.3.47/linux/drivers/char/ChangeLog Thu Nov 9 11:23:48 1995 +++ linux/drivers/char/ChangeLog Thu Dec 14 08:16:52 1995 @@ -1,3 +1,14 @@ +Tue Dec 5 13:21:27 1995 + + * 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 * tty_io.c (tty_init): Move registration of TTY_MAJOR and diff -u --recursive --new-file v1.3.47/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v1.3.47/linux/drivers/char/busmouse.c Tue Nov 21 13:22:09 1995 +++ linux/drivers/char/busmouse.c Thu Dec 14 08:16:53 1995 @@ -30,6 +30,7 @@ * Replaced dumb busy loop with udelay() 16 Nov 95 * Nathan Laredo * + * Track I/O ports with request_region(). 12 Dec 95 Philip Blundell */ #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -137,7 +139,7 @@ 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 @@ 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 @@ } 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 @@ 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 @@ void cleanup_module(void) { mouse_deregister(&bus_mouse); + release_region(LOGIBM_BASE, LOGIBM_EXTENT); } #endif diff -u --recursive --new-file v1.3.47/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v1.3.47/linux/drivers/char/serial.c Tue Oct 10 18:46:34 1995 +++ linux/drivers/char/serial.c Thu Dec 14 08:16:52 1995 @@ -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 + * * This module exports the following rs232 io functions: * * int rs_init(void); @@ -455,6 +457,19 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) diff -u --recursive --new-file v1.3.47/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v1.3.47/linux/drivers/net/8390.c Wed Dec 13 09:02:46 1995 +++ linux/drivers/net/8390.c Fri Dec 15 06:45:43 1995 @@ -612,9 +612,7 @@ 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); diff -u --recursive --new-file v1.3.47/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v1.3.47/linux/drivers/net/de4x5.c Mon Dec 11 15:42:03 1995 +++ linux/drivers/net/de4x5.c Fri Dec 15 06:46:15 1995 @@ -716,9 +716,7 @@ 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; diff -u --recursive --new-file v1.3.47/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v1.3.47/linux/drivers/net/ewrk3.c Sat Nov 25 19:04:46 1995 +++ linux/drivers/net/ewrk3.c Fri Dec 15 06:46:30 1995 @@ -625,9 +625,7 @@ 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; diff -u --recursive --new-file v1.3.47/linux/drivers/net/znet.c linux/drivers/net/znet.c --- v1.3.47/linux/drivers/net/znet.c Sat Nov 25 19:04:47 1995 +++ linux/drivers/net/znet.c Fri Dec 15 06:47:26 1995 @@ -623,7 +623,6 @@ 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 @@ } #endif } -#endif void show_dma(void) { diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v1.3.47/linux/drivers/scsi/Config.in Fri Nov 17 08:42:26 1995 +++ linux/drivers/scsi/Config.in Thu Dec 14 08:16:51 1995 @@ -23,15 +23,15 @@ 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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v1.3.47/linux/drivers/scsi/Makefile Fri Nov 17 08:42:26 1995 +++ linux/drivers/scsi/Makefile Thu Dec 14 15:44:09 1995 @@ -18,7 +18,7 @@ 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 @@ 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 @@ 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 @@ 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) diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/README.st linux/drivers/scsi/README.st --- v1.3.47/linux/drivers/scsi/README.st Wed Sep 27 15:59:59 1995 +++ linux/drivers/scsi/README.st Sun Dec 17 10:59:24 1995 @@ -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 @@ 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 @@ 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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v1.3.47/linux/drivers/scsi/aha152x.c Wed Dec 13 09:02:46 1995 +++ linux/drivers/scsi/aha152x.c Thu Dec 14 15:45:44 1995 @@ -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 * @@ -145,7 +151,7 @@ * Revision 0.0 1993/08/14 19:54:25 root * empty function bodies; detect() works. * - + * ************************************************************************** @@ -158,23 +164,28 @@ 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=[,[,[,[,]]]] + aha152x=[,[,[,[,[,]]]]] 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: @@ -225,7 +236,7 @@ #include #include "aha152x.h" -#include +#include struct proc_dir_entry proc_scsi_aha152x = { PROC_SCSI_AHA152X, 7, "aha152x", @@ -241,26 +252,10 @@ #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 -#endif -#if !defined(PARITY) -#error undefined PARITY; define AUTOCONF or PARITY -#endif +#if !defined(AUTOCONF) && !defined(SETUP0) +#error define AUTOCONF or SETUP0 #endif -/* I use this when I'm looking for weird bugs */ -#define DEBUG_TIMING - #if defined(DEBUG_AHA152X) #undef SKIP_PORTS /* don't display ports */ @@ -287,6 +282,7 @@ #if 0 #endif +#define DEBUG_SELECTION #define DEBUG_PHASES #define DEBUG_RESET #define DEBUG_ABORT @@ -297,66 +293,89 @@ /* 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 -static int setup_debug = 0; + int debug; #endif +} setup[2]; -static char *setup_str = (char *)NULL; +static struct Scsi_Host *aha152x_host[IRQS]; -enum { - not_issued = 0x01, - in_selection = 0x02, - disconnected = 0x04, - aborted = 0x08, - sent_ident = 0x10, - in_other = 0x20, -}; +#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; -/* - * 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; + unsigned char syncrate[8]; + + unsigned char message[256]; + int message_len; -static int aborting=0, abortion_complete=0, abort_result; +#ifdef DEBUG_AHA152X + int debug; +#endif +}; -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 @@ 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 @@ (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 @@ { "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 @@ /* * 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 @@ *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 @@ 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 @@ /* * 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 @@ * 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 @@ } /* 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; + if(setup_count>2) + panic("aha152x: you can only configure up to two controllers\n"); - 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; + 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=[,[," + "[,[,[,,[,]]]]]]\n"); +#else + if(ints[0]>6) + { + printk("aha152x: usage: aha152x=[,[," + "[,[,[,]]]]]\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; iio_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; i6) -#else - if(setup_called>5) -#endif + for(i=0; i[,[,[,[,[,]]]]]\n"); -#else - printk("aha152x: usage: aha152x=[,[,[,[,]]]]\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 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 @@ printk("aha152x: "); #endif /* !SKIP_BIOSTEST */ -#if !defined(PORTBASE) - printk("porttest: "); - for( i=0; iio_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); + 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"); - 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; + 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 @@ 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 @@ /* 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 @@ } /* - * 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 @@ * 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 @@ 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 @@ 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 @@ /* 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 @@ /* 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 @@ /* * 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 @@ SETPORT(SCSISEQ, 0); SETPORT(SXFRCTL1, 0); - SETPORT( SCSISIG, 0); + SETPORT(SCSISIG, 0); SETPORT(SCSIRATE, 0); /* clear all interrupt conditions */ @@ -1031,45 +1084,47 @@ 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 @@ 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 @@ } 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 @@ 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 @@ /* * 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 @@ 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 @@ /* * 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ /* 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; idebug & 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 @@ 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)); - - /* reset fifo and enable writes */ - SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); - SETPORT(DMACNTRL0, ENDMA|WRITE_READ); - - /* clear transfer count and scsi fifo */ - SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 ); - SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); - - /* 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 ) ) + int i; + + 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( TESTHI( SSTAT1, PHASEMIS ) ) - aha152x_panic("target left COMMAND phase"); - -#if defined(DEBUG_CMD) - if(aha152x_debug & debug_cmd) + for(i=0; icmd_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, ¤t_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(icmd_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; idebug & debug_msgi) + print_msg(buffer); #endif - make_acklow(); - if(getphase()!=P_MSGI) + 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 @@ 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 @@ { 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 @@ } #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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ /* * 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 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 @@ 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 @@ /* * Dump the queued data */ -static void show_queues(void) +static void show_queues(struct Scsi_Host *shpnt) { unsigned long flags; Scsi_Cmnd *ptr; @@ -2618,22 +2693,241 @@ 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; icmnd[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; ihost_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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h --- v1.3.47/linux/drivers/scsi/aha152x.h Mon Oct 23 18:02:07 1995 +++ linux/drivers/scsi/aha152x.h Thu Dec 14 15:44:10 1995 @@ -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_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 @@ /* 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 */ diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c --- v1.3.47/linux/drivers/scsi/constants.c Wed Dec 13 09:02:46 1995 +++ linux/drivers/scsi/constants.c Thu Dec 14 06:44:58 1995 @@ -593,7 +593,7 @@ } #else void print_hostbyte(int scsiresult) -{ printk("Hostbyte=0x%02x ",hostbyte(scsiresult)); +{ printk("Hostbyte=0x%02x ",host_byte(scsiresult)); } #endif diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v1.3.47/linux/drivers/scsi/g_NCR5380.c Mon Oct 23 18:02:11 1995 +++ linux/drivers/scsi/g_NCR5380.c Thu Dec 14 08:16:51 1995 @@ -177,3 +177,10 @@ } #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 +#include "scsi_module.c" +#endif diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/g_NCR5380.h linux/drivers/scsi/g_NCR5380.h --- v1.3.47/linux/drivers/scsi/g_NCR5380.h Mon Sep 18 14:53:57 1995 +++ linux/drivers/scsi/g_NCR5380.h Thu Dec 14 08:16:52 1995 @@ -51,8 +51,7 @@ #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 @@ 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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c --- v1.3.47/linux/drivers/scsi/pas16.c Mon Oct 23 18:02:11 1995 +++ linux/drivers/scsi/pas16.c Thu Dec 14 08:16:52 1995 @@ -539,3 +539,11 @@ } #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 +#include "scsi_module.c" +#endif diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/pas16.h linux/drivers/scsi/pas16.h --- v1.3.47/linux/drivers/scsi/pas16.h Mon Sep 18 14:54:01 1995 +++ linux/drivers/scsi/pas16.h Thu Dec 14 08:16:52 1995 @@ -138,7 +138,7 @@ * 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 @@ /* 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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v1.3.47/linux/drivers/scsi/st.c Thu Nov 9 11:23:51 1995 +++ linux/drivers/scsi/st.c Sun Dec 17 10:59:24 1995 @@ -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 */ @@ -34,6 +34,11 @@ 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 #include "scsi.h" @@ -114,7 +119,8 @@ 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 @@ ((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 @@ 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 @@ } #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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ #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 @@ (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 @@ 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 @@ #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 @@ 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_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 @@ 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 @@ #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 @@ 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 @@ #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 @@ #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 @@ #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 @@ 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 @@ 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 @@ return retval; } } - if (STp->eof == ST_EOM_OK) return (-ENOSPC); else if (STp->eof == ST_EOM_ERROR) @@ -852,7 +862,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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 @@ (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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ #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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ #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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } 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 @@ #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 @@ #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 @@ { 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 @@ 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 @@ (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 @@ (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 @@ 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 @@ 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; } } diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st.h linux/drivers/scsi/st.h --- v1.3.47/linux/drivers/scsi/st.h Mon Oct 23 18:02:12 1995 +++ linux/drivers/scsi/st.h Sun Dec 17 10:59:24 1995 @@ -45,6 +45,7 @@ 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; diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st_options.h linux/drivers/scsi/st_options.h --- v1.3.47/linux/drivers/scsi/st_options.h Wed Sep 27 15:59:59 1995 +++ linux/drivers/scsi/st_options.h Sun Dec 17 10:59:24 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c --- v1.3.47/linux/drivers/scsi/t128.c Mon Oct 23 18:02:12 1995 +++ linux/drivers/scsi/t128.c Thu Dec 14 08:16:52 1995 @@ -393,3 +393,10 @@ } #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 diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/t128.h linux/drivers/scsi/t128.h --- v1.3.47/linux/drivers/scsi/t128.h Mon Sep 18 14:54:04 1995 +++ linux/drivers/scsi/t128.h Thu Dec 14 08:16:52 1995 @@ -115,7 +115,7 @@ * 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 @@ /* 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 diff -u --recursive --new-file v1.3.47/linux/fs/buffer.c linux/fs/buffer.c --- v1.3.47/linux/fs/buffer.c Mon Dec 11 15:42:03 1995 +++ linux/fs/buffer.c Thu Dec 14 08:16:52 1995 @@ -588,7 +588,7 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ { 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 @@ 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 @@ 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; isizeb_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 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; }; diff -u --recursive --new-file v1.3.47/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- v1.3.47/linux/fs/hpfs/hpfs_fs.c Mon Dec 11 15:42:04 1995 +++ linux/fs/hpfs/hpfs_fs.c Sun Dec 17 11:17:20 1995 @@ -232,7 +232,7 @@ /* 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 @@ int lowercase; int conv; int dubious; + int nocheck; MOD_INC_USE_COUNT; @@ -351,7 +352,8 @@ * 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 @@ * so don't */ - if (dubious) + if (dubious && !nocheck) goto bail2; dubious |= check_warn((spareblock->n_dnode_spares != @@ -544,7 +546,7 @@ */ 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 @@ *umask = current->fs->umask; *lowercase = 1; *conv = CONV_BINARY; + *nocheck = 0; if (!opts) return 1; @@ -599,6 +602,8 @@ else return 0; } + else if (!strcmp(p,"nocheck")) + *nocheck=1; else return 1; } diff -u --recursive --new-file v1.3.47/linux/fs/inode.c linux/fs/inode.c --- v1.3.47/linux/fs/inode.c Mon Dec 11 15:42:04 1995 +++ linux/fs/inode.c Fri Dec 15 07:25:02 1995 @@ -150,7 +150,7 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v1.3.47/linux/fs/msdos/file.c linux/fs/msdos/file.c --- v1.3.47/linux/fs/msdos/file.c Sat Nov 11 17:41:33 1995 +++ linux/fs/msdos/file.c Sun Dec 17 11:02:41 1995 @@ -283,8 +283,8 @@ 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 @@ { 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; diff -u --recursive --new-file v1.3.47/linux/fs/msdos/inode.c linux/fs/msdos/inode.c --- v1.3.47/linux/fs/msdos/inode.c Mon Dec 11 15:42:04 1995 +++ linux/fs/msdos/inode.c Sun Dec 17 11:02:41 1995 @@ -81,7 +81,9 @@ *check = 'n'; *conversion = 'b'; - *dotsOK =0; + /* Please leave dotsOK as 1, and contact Albert Cahalan if */ + /* it causes any problems for you. */ + *dotsOK =1; /* see note above, and report problems */ *uid = current->uid; *gid = current->gid; *umask = current->fs->umask; @@ -427,6 +429,8 @@ 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; diff -u --recursive --new-file v1.3.47/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v1.3.47/linux/fs/msdos/namei.c Mon Nov 27 12:48:32 1995 +++ linux/fs/msdos/namei.c Sun Dec 17 11:02:41 1995 @@ -452,7 +452,7 @@ res = -EPERM; goto unlink_done; } - if (MSDOS_I(inode)->i_attrs & ATTR_SYS){ + if (IS_IMMUTABLE(inode)){ res = -EPERM; goto unlink_done; } diff -u --recursive --new-file v1.3.47/linux/fs/namei.c linux/fs/namei.c --- v1.3.47/linux/fs/namei.c Mon Dec 11 15:42:04 1995 +++ linux/fs/namei.c Fri Dec 15 08:35:33 1995 @@ -371,7 +371,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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, diff -u --recursive --new-file v1.3.47/linux/fs/open.c linux/fs/open.c --- v1.3.47/linux/fs/open.c Mon Dec 11 15:42:04 1995 +++ linux/fs/open.c Fri Dec 15 08:07:31 1995 @@ -367,6 +367,7 @@ 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 @@ 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 @@ 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); } diff -u --recursive --new-file v1.3.47/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c --- v1.3.47/linux/fs/umsdos/inode.c Thu Nov 9 11:23:52 1995 +++ linux/fs/umsdos/inode.c Sun Dec 17 11:02:41 1995 @@ -404,6 +404,7 @@ 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); diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v1.3.47/linux/include/asm-alpha/pgtable.h Mon Dec 11 15:42:04 1995 +++ linux/include/asm-alpha/pgtable.h Fri Dec 15 07:31:30 1995 @@ -9,17 +9,62 @@ * in (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 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)) diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v1.3.47/linux/include/asm-alpha/processor.h Sun Oct 29 11:38:49 1995 +++ linux/include/asm-alpha/processor.h Fri Dec 15 12:48:37 1995 @@ -46,6 +46,9 @@ 0, 0, 0, \ } +#define alloc_kernel_stack() get_free_page(GFP_KERNEL) +#define free_kernel_stack(page) free_page((page)) + #include /* diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h --- v1.3.47/linux/include/asm-alpha/termios.h Thu Jul 13 16:20:21 1995 +++ linux/include/asm-alpha/termios.h Thu Dec 14 08:16:52 1995 @@ -102,6 +102,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 -u --recursive --new-file v1.3.47/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h --- v1.3.47/linux/include/asm-i386/bugs.h Wed Nov 8 07:11:41 1995 +++ linux/include/asm-i386/bugs.h Sun Dec 17 11:17:18 1995 @@ -110,8 +110,25 @@ 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; diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v1.3.47/linux/include/asm-i386/pgtable.h Wed Dec 13 09:02:47 1995 +++ linux/include/asm-i386/pgtable.h Fri Dec 15 07:33:13 1995 @@ -1,6 +1,8 @@ #ifndef _I386_PGTABLE_H #define _I386_PGTABLE_H +#include + /* * 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 @@ __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 @@ invalidate(); } -static inline void invalidate_page(struct mm_struct *mm, +static inline void invalidate_page(struct vm_area_struct *vma, unsigned long addr) { invalidate(); diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v1.3.47/linux/include/asm-i386/processor.h Thu Sep 7 17:17:19 1995 +++ linux/include/asm-i386/processor.h Fri Dec 15 12:48:37 1995 @@ -124,6 +124,9 @@ 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; diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h --- v1.3.47/linux/include/asm-i386/termios.h Thu Jul 13 16:20:21 1995 +++ linux/include/asm-i386/termios.h Thu Dec 14 08:16:52 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/a.out.h linux/include/asm-mips/a.out.h --- v1.3.47/linux/include/asm-mips/a.out.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/a.out.h Wed Dec 13 12:39:45 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/asm.h linux/include/asm-mips/asm.h --- v1.3.47/linux/include/asm-mips/asm.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/asm.h Wed Dec 13 12:39:45 1995 @@ -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 +#include +#include + +#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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v1.3.47/linux/include/asm-mips/bitops.h Sun Oct 29 11:38:49 1995 +++ linux/include/asm-mips/bitops.h Wed Dec 13 12:39:45 1995 @@ -10,8 +10,12 @@ #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 /* @@ -62,14 +66,19 @@ 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 #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 @@ #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 @@ __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; diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h --- v1.3.47/linux/include/asm-mips/bootinfo.h Wed Jan 18 08:54:13 1995 +++ linux/include/asm-mips/bootinfo.h Thu Dec 14 08:16:53 1995 @@ -11,20 +11,25 @@ * 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 @@ -47,15 +52,16 @@ #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 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 @@ /* * 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 @@ }; +#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 @@ * 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 @@ #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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h --- v1.3.47/linux/include/asm-mips/byteorder.h Tue Aug 15 20:39:04 1995 +++ linux/include/asm-mips/byteorder.h Wed Dec 13 12:39:45 1995 @@ -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 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 @@ ((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 @@ ((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) diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/cachectl.h linux/include/asm-mips/cachectl.h --- v1.3.47/linux/include/asm-mips/cachectl.h Fri Jan 13 20:28:54 1995 +++ linux/include/asm-mips/cachectl.h Wed Dec 13 12:39:45 1995 @@ -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 @@ -20,13 +18,20 @@ #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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h --- v1.3.47/linux/include/asm-mips/checksum.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/checksum.h Wed Dec 13 12:39:45 1995 @@ -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 , 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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h --- v1.3.47/linux/include/asm-mips/delay.h Fri Jan 13 20:42:03 1995 +++ linux/include/asm-mips/delay.h Wed Dec 13 12:39:45 1995 @@ -27,15 +27,16 @@ 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) { diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/dma.h linux/include/asm-mips/dma.h --- v1.3.47/linux/include/asm-mips/dma.h Wed Aug 2 13:21:16 1995 +++ linux/include/asm-mips/dma.h Wed Dec 13 12:39:45 1995 @@ -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 @@ -69,10 +73,12 @@ #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 @@ 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- v1.3.47/linux/include/asm-mips/elf.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/elf.h Wed Dec 13 12:39:45 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h --- v1.3.47/linux/include/asm-mips/errno.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/errno.h Wed Dec 13 12:39:45 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h --- v1.3.47/linux/include/asm-mips/fcntl.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/fcntl.h Wed Dec 13 12:39:45 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v1.3.47/linux/include/asm-mips/floppy.h Thu Nov 9 11:23:52 1995 +++ linux/include/asm-mips/floppy.h Wed Dec 13 12:39:45 1995 @@ -17,7 +17,7 @@ #include #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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/fpregdef.h linux/include/asm-mips/fpregdef.h --- v1.3.47/linux/include/asm-mips/fpregdef.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/fpregdef.h Wed Dec 13 12:39:45 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/gdb-stub.h linux/include/asm-mips/gdb-stub.h --- v1.3.47/linux/include/asm-mips/gdb-stub.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/gdb-stub.h Wed Dec 13 12:39:45 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/io.h linux/include/asm-mips/io.h --- v1.3.47/linux/include/asm-mips/io.h Sun Jan 15 23:05:43 1995 +++ linux/include/asm-mips/io.h Wed Dec 13 12:39:45 1995 @@ -1,8 +1,8 @@ #ifndef __ASM_MIPS_IO_H #define __ASM_MIPS_IO_H -#include #include +#include /* * This file contains the definitions for the MIPS counterpart of the @@ -47,6 +47,51 @@ #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 @@ #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 @@ ".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 @@ : "$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 @@ : "$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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h --- v1.3.47/linux/include/asm-mips/ioctl.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/ioctl.h Wed Dec 13 12:39:45 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h --- v1.3.47/linux/include/asm-mips/ioctls.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/ioctls.h Wed Dec 13 12:39:45 1995 @@ -0,0 +1,299 @@ +#ifndef __ASM_MIPS_IOCTLS_H +#define __ASM_MIPS_IOCTLS_H + +#include + +#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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h --- v1.3.47/linux/include/asm-mips/irq.h Fri Jan 13 20:39:49 1995 +++ linux/include/asm-mips/irq.h Wed Dec 13 12:39:46 1995 @@ -12,6 +12,11 @@ #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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h --- v1.3.47/linux/include/asm-mips/jazz.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/jazz.h Wed Dec 13 12:39:46 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v1.3.47/linux/include/asm-mips/jazzdma.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/jazzdma.h Wed Dec 13 12:39:46 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h --- v1.3.47/linux/include/asm-mips/mc146818rtc.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/mc146818rtc.h Wed Dec 13 12:39:46 1995 @@ -0,0 +1,28 @@ +/* + * Machine dependend access functions for RTC registers. + */ +#ifndef __ASM_MIPS_MC146818RTC_H +#define __ASM_MIPS_MC146818RTC_H + +#include +#include + +#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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mipsconfig.h linux/include/asm-mips/mipsconfig.h --- v1.3.47/linux/include/asm-mips/mipsconfig.h Tue Jan 17 00:57:01 1995 +++ linux/include/asm-mips/mipsconfig.h Wed Dec 13 12:39:46 1995 @@ -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 @@ -31,14 +28,31 @@ * 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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h --- v1.3.47/linux/include/asm-mips/mipsregs.h Tue Jan 17 00:57:01 1995 +++ linux/include/asm-mips/mipsregs.h Wed Dec 13 12:39:46 1995 @@ -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 @@ -59,6 +57,9 @@ #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 @@ -66,6 +67,12 @@ #define CP0_ERROREPC $30 /* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* * Values for PageMask register */ #define PM_4K 0x00000000 @@ -88,33 +95,84 @@ #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 * @@ -122,54 +180,89 @@ * 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/mman.h linux/include/asm-mips/mman.h --- v1.3.47/linux/include/asm-mips/mman.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/mman.h Wed Dec 13 12:39:46 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/page.h linux/include/asm-mips/page.h --- v1.3.47/linux/include/asm-mips/page.h Wed Nov 8 07:11:41 1995 +++ linux/include/asm-mips/page.h Wed Dec 13 12:39:46 1995 @@ -1,36 +1,33 @@ #ifndef __ASM_MIPS_PAGE_H #define __ASM_MIPS_PAGE_H -#define STRICT_MM_TYPECHECKS - -#ifndef __ASSEMBLY__ - -#include +/* 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 @@ * .. 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.. - */ -#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__ - -#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.. + * 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. */ -extern pte_t __bad_page(void); -extern pte_t * __bad_pagetable(void); - -extern unsigned long __zero_page(void); +extern void __copy_page(unsigned long from, unsigned long to); +#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to) -#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<> 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v1.3.47/linux/include/asm-mips/pgtable.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/pgtable.h Wed Dec 13 12:39:46 1995 @@ -0,0 +1,570 @@ +#ifndef __ASM_MIPS_PGTABLE_H +#define __ASM_MIPS_PGTABLE_H + +#ifndef __LANGUAGE_ASSEMBLY__ + +#include +#include + +/* + * 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<>(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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/pica.h linux/include/asm-mips/pica.h --- v1.3.47/linux/include/asm-mips/pica.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/pica.h Wed Dec 13 12:39:46 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v1.3.47/linux/include/asm-mips/processor.h Thu Feb 9 18:22:17 1995 +++ linux/include/asm-mips/processor.h Wed Dec 13 12:39:46 1995 @@ -8,7 +8,10 @@ #ifndef __ASM_MIPS_PROCESSOR_H #define __ASM_MIPS_PROCESSOR_H -#if !defined (__ASSEMBLY__) +#if !defined (__LANGUAGE_ASSEMBLY__) +#include +#include +#include #include /* @@ -19,46 +22,6 @@ 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 @@ }; #define INIT_FPU { \ - 0, \ + {{0,},} \ } /* @@ -128,17 +91,18 @@ */ 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 @@ #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 @@ /* \ * 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 @@ #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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h --- v1.3.47/linux/include/asm-mips/ptrace.h Wed Jan 18 08:54:13 1995 +++ linux/include/asm-mips/ptrace.h Wed Dec 13 12:39:46 1995 @@ -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 - -/* - * 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 @@ */ 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/reg.h linux/include/asm-mips/reg.h --- v1.3.47/linux/include/asm-mips/reg.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/reg.h Wed Dec 13 12:39:46 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/regdef.h linux/include/asm-mips/regdef.h --- v1.3.47/linux/include/asm-mips/regdef.h Fri Jan 13 20:38:36 1995 +++ linux/include/asm-mips/regdef.h Wed Dec 13 12:39:46 1995 @@ -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 */ @@ -40,11 +40,13 @@ #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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h --- v1.3.47/linux/include/asm-mips/resource.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/resource.h Wed Dec 13 12:39:46 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/segment.h linux/include/asm-mips/segment.h --- v1.3.47/linux/include/asm-mips/segment.h Wed Jan 25 08:54:23 1995 +++ linux/include/asm-mips/segment.h Wed Dec 13 12:39:46 1995 @@ -7,81 +7,119 @@ * * 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 /* - * 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 get_fs_word(addr) get_user_word((short *)(addr)) -static inline unsigned short get_user_word(const short *addr) -{ - return *addr; -} - -#define get_fs_long(addr) get_user_long((int *)(addr)) -static inline unsigned long get_user_long(const int *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_dlong(addr) get_user_dlong((long long *)(addr)) -static inline unsigned long get_user_dlong(const long long *addr) -{ - return *addr; -} - -#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 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_long(x,addr) put_user_long((x),(int *)(addr)) -static inline void put_user_long(unsigned long val,int * addr) -{ - *addr = val; -} +/* + * 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 put_fs_dlong(x,addr) put_user_dlong((x),(int *)(addr)) -static inline void put_user_dlong(unsigned long val,long long * addr) +/* I should make this use unaligned transfers etc.. */ +static inline void __put_user(unsigned long x, void * y, int size) { - *addr = val; + __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(); +} + +/* I should make this use unaligned transfers etc.. */ +static inline unsigned long __get_user(const void * y, int size) +{ + 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 get_fs_byte(addr) get_user((unsigned char *)(addr)) +#define get_fs_word(addr) get_user((unsigned short *)(addr)) +#define get_fs_long(addr) get_user((unsigned int *)(addr)) +#define get_fs_quad(addr) get_user((unsigned long *)(addr)) + +#define put_fs_byte(x,addr) put_user((x),(char *)(addr)) +#define put_fs_word(x,addr) put_user((x),(short *)(addr)) +#define put_fs_long(x,addr) put_user((x),(int *)(addr)) +#define put_fs_quad(x,addr) put_user((x),(long *)(addr)) + +static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) +{ + __gcc_barrier(); + memcpy(to, from, n); + __gcc_barrier(); +} + +static inline void memcpy_tofs(void * to, const void * from, unsigned long n) +{ + __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 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/shmparam.h linux/include/asm-mips/shmparam.h --- v1.3.47/linux/include/asm-mips/shmparam.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/shmparam.h Wed Dec 13 12:39:46 1995 @@ -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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h --- v1.3.47/linux/include/asm-mips/sigcontext.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/sigcontext.h Wed Dec 13 12:39:46 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h --- v1.3.47/linux/include/asm-mips/signal.h Wed Jan 18 08:54:13 1995 +++ linux/include/asm-mips/signal.h Wed Dec 13 12:39:46 1995 @@ -1,16 +1,126 @@ #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 +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 +#endif #endif /* __ASM_MIPS_SIGNAL_H */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h --- v1.3.47/linux/include/asm-mips/socket.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/socket.h Wed Dec 13 12:39:46 1995 @@ -0,0 +1,58 @@ +#ifndef __ASM_MIPS_SOCKET_H +#define __ASM_MIPS_SOCKET_H + +#include +#include + +/* 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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h --- v1.3.47/linux/include/asm-mips/stackframe.h Fri Jan 13 20:37:30 1995 +++ linux/include/asm-mips/stackframe.h Wed Dec 13 12:39:46 1995 @@ -11,18 +11,12 @@ /* * 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 + * 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. */ - -/* - * Offsets into the Interrupt stackframe. - * The first 20 bytes are reserved for the usual MIPS calling sequence - */ -#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) @@ -74,121 +68,122 @@ */ #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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/stat.h linux/include/asm-mips/stat.h --- v1.3.47/linux/include/asm-mips/stat.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/stat.h Wed Dec 13 12:39:46 1995 @@ -0,0 +1,55 @@ +#ifndef __ASM_MIPS_STAT_H +#define __ASM_MIPS_STAT_H + +#include + +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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/statfs.h linux/include/asm-mips/statfs.h --- v1.3.47/linux/include/asm-mips/statfs.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/statfs.h Wed Dec 13 12:39:47 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/string.h linux/include/asm-mips/string.h --- v1.3.47/linux/include/asm-mips/string.h Sat Jan 14 01:15:15 1995 +++ linux/include/asm-mips/string.h Wed Dec 13 12:39:47 1995 @@ -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 - +#define __HAVE_ARCH_STRCPY extern __inline__ char * strcpy(char * dest, const char *src) { char *xdest = dest; @@ -22,10 +20,10 @@ ".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 @@ 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 @@ return dest; } +#define __HAVE_ARCH_STRCMP extern __inline__ int strcmp(const char * cs, const char * ct) { int __res; @@ -71,16 +71,18 @@ ".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 @@ 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 @@ "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 @@ return __res; } +#define __HAVE_ARCH_MEMSET extern __inline__ void * memset(void * s, int c, size_t count) { void *xs = s; @@ -133,6 +137,7 @@ 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 @@ ".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 @@ 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 @@ ".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 @@ ".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 @@ 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/sysmips.h linux/include/asm-mips/sysmips.h --- v1.3.47/linux/include/asm-mips/sysmips.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/sysmips.h Wed Dec 13 12:39:47 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v1.3.47/linux/include/asm-mips/system.h Fri Jan 13 20:37:06 1995 +++ linux/include/asm-mips/system.h Wed Dec 13 12:39:47 1995 @@ -5,81 +5,108 @@ * 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 -#include -#include -#include +#include -/* - * (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 @@ 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 @@ /* * 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 @@ "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 @@ "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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/termbits.h linux/include/asm-mips/termbits.h --- v1.3.47/linux/include/asm-mips/termbits.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/termbits.h Wed Dec 13 12:39:47 1995 @@ -0,0 +1,35 @@ +#ifndef __ASM_MIPS_TERMBITS_H +#define __ASM_MIPS_TERMBITS_H + +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h --- v1.3.47/linux/include/asm-mips/termios.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/termios.h Wed Dec 13 12:39:47 1995 @@ -0,0 +1,49 @@ +#ifndef __ASM_MIPS_TERMIOS_H +#define __ASM_MIPS_TERMIOS_H + +#include +#include + +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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/types.h linux/include/asm-mips/types.h --- v1.3.47/linux/include/asm-mips/types.h Tue Jan 10 03:34:06 1995 +++ linux/include/asm-mips/types.h Wed Dec 13 12:39:47 1995 @@ -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 __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 @@ #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 . + * 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 */ diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h --- v1.3.47/linux/include/asm-mips/unistd.h Thu Jan 12 00:54:19 1995 +++ linux/include/asm-mips/unistd.h Wed Dec 13 12:39:47 1995 @@ -1,43 +1,1191 @@ +/* + * 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 /* - * 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 @@ 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 @@ 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 @@ 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 @@ 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/user.h linux/include/asm-mips/user.h --- v1.3.47/linux/include/asm-mips/user.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/user.h Wed Dec 13 12:39:47 1995 @@ -0,0 +1,52 @@ +#ifndef __ASM_MIPS_USER_H +#define __ASM_MIPS_USER_H + +#include + +#include +#include + +/* + * 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 -u --recursive --new-file v1.3.47/linux/include/asm-mips/vector.h linux/include/asm-mips/vector.h --- v1.3.47/linux/include/asm-mips/vector.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-mips/vector.h Wed Dec 13 12:39:47 1995 @@ -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 */ diff -u --recursive --new-file v1.3.47/linux/include/linux/a.out.h linux/include/linux/a.out.h --- v1.3.47/linux/include/linux/a.out.h Fri Jun 16 22:02:55 1995 +++ linux/include/linux/a.out.h Wed Dec 13 12:39:47 1995 @@ -33,6 +33,8 @@ #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) diff -u --recursive --new-file v1.3.47/linux/include/linux/blk.h linux/include/linux/blk.h --- v1.3.47/linux/include/linux/blk.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/blk.h Fri Dec 15 12:56:00 1995 @@ -78,11 +78,14 @@ #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 @@ #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 @@ 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; diff -u --recursive --new-file v1.3.47/linux/include/linux/busmouse.h linux/include/linux/busmouse.h --- v1.3.47/linux/include/linux/busmouse.h Tue Nov 21 13:22:13 1995 +++ linux/include/linux/busmouse.h Thu Dec 14 08:16:53 1995 @@ -33,11 +33,13 @@ /*--------- 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 @@ -59,10 +61,12 @@ /*--------- 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 diff -u --recursive --new-file v1.3.47/linux/include/linux/fs.h linux/include/linux/fs.h --- v1.3.47/linux/include/linux/fs.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/fs.h Fri Dec 15 08:07:26 1995 @@ -15,8 +15,6 @@ #include #include -#include - /* * 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 @@ -114,6 +112,9 @@ #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ #ifdef __KERNEL__ + +#include + 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 @@ #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) */ @@ -178,6 +180,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 diff -u --recursive --new-file v1.3.47/linux/include/linux/major.h linux/include/linux/major.h --- v1.3.47/linux/include/linux/major.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/major.h Thu Dec 14 08:16:52 1995 @@ -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 diff -u --recursive --new-file v1.3.47/linux/include/linux/mount.h linux/include/linux/mount.h --- v1.3.47/linux/include/linux/mount.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/mount.h Fri Dec 15 07:31:39 1995 @@ -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 *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 */ diff -u --recursive --new-file v1.3.47/linux/include/linux/serial.h linux/include/linux/serial.h --- v1.3.47/linux/include/linux/serial.h Fri Oct 6 14:35:16 1995 +++ linux/include/linux/serial.h Thu Dec 14 08:26:30 1995 @@ -97,6 +97,16 @@ 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 @@ #include #include +/* + * 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 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; }; diff -u --recursive --new-file v1.3.47/linux/init/main.c linux/init/main.c --- v1.3.47/linux/init/main.c Mon Dec 11 15:42:06 1995 +++ linux/init/main.c Thu Dec 14 08:16:52 1995 @@ -49,7 +49,6 @@ 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 @@ #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 @@ 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 @@ } 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 @@ { 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 @@ 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(); diff -u --recursive --new-file v1.3.47/linux/kernel/exit.c linux/kernel/exit.c --- v1.3.47/linux/kernel/exit.c Fri Nov 17 08:42:29 1995 +++ linux/kernel/exit.c Fri Dec 15 12:48:37 1995 @@ -96,7 +96,7 @@ 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 @@ /* * 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 diff -u --recursive --new-file v1.3.47/linux/kernel/fork.c linux/kernel/fork.c --- v1.3.47/linux/kernel/fork.c Tue Nov 21 13:22:14 1995 +++ linux/kernel/fork.c Fri Dec 15 12:48:37 1995 @@ -206,7 +206,7 @@ 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 @@ 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: diff -u --recursive --new-file v1.3.47/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.3.47/linux/kernel/ksyms.c Wed Dec 13 09:02:47 1995 +++ linux/kernel/ksyms.c Sun Dec 17 11:17:18 1995 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -342,6 +343,7 @@ 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 @@ 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 -u --recursive --new-file v1.3.47/linux/lib/inflate.c linux/lib/inflate.c --- v1.3.47/linux/lib/inflate.c Thu Jan 1 02:00:00 1970 +++ linux/lib/inflate.c Thu Dec 14 08:16:52 1995 @@ -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 +# include +#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())<>=(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(""); + 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(" 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(" 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(""); + + /* 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; +} + + diff -u --recursive --new-file v1.3.47/linux/mm/filemap.c linux/mm/filemap.c --- v1.3.47/linux/mm/filemap.c Wed Dec 13 09:02:47 1995 +++ linux/mm/filemap.c Fri Dec 15 07:31:39 1995 @@ -142,7 +142,7 @@ 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 @@ 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; diff -u --recursive --new-file v1.3.47/linux/mm/memory.c linux/mm/memory.c --- v1.3.47/linux/mm/memory.c Wed Dec 13 09:02:47 1995 +++ linux/mm/memory.c Fri Dec 15 07:31:39 1995 @@ -59,7 +59,19 @@ 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 @@ } 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 @@ 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 @@ 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; } diff -u --recursive --new-file v1.3.47/linux/mm/swap.c linux/mm/swap.c --- v1.3.47/linux/mm/swap.c Wed Dec 13 09:02:47 1995 +++ linux/mm/swap.c Fri Dec 15 07:31:39 1995 @@ -457,7 +457,7 @@ 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 @@ } 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; diff -u --recursive --new-file v1.3.47/linux/net/netlink.c linux/net/netlink.c --- v1.3.47/linux/net/netlink.c Mon Dec 11 15:42:11 1995 +++ linux/net/netlink.c Thu Dec 14 08:07:07 1995 @@ -193,7 +193,7 @@ int netlink_post(int unit, struct sk_buff *skb) { unsigned long flags; - int ret=0; + int ret=-EUNATCH; if(open_map&(1<