diff -u --recursive --new-file v2.1.43/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.43/linux/Documentation/Configure.help Mon Jun 16 16:35:53 1997 +++ linux/Documentation/Configure.help Thu Jun 26 12:33:36 1997 @@ -287,17 +287,19 @@ Linux. This may slow disk throughput by a few percent, but at least things will operate 100% reliably. If unsure, say Y. -Intel 82371 PIIX (Triton I/II) DMA support +Intel 82371 PIIX (Triton I/II), VIA VP-1 DMA support CONFIG_BLK_DEV_TRITON If your PCI system uses an IDE harddrive (as opposed to SCSI, say) and includes the Intel Triton I/II IDE interface chipset (i82371FB, - i82371SB or i82371AB), you will want to enable this option to allow - use of bus-mastering DMA data transfers. Read the comments at the + i82371SB or i82371AB), or the VIA VP-1 IDE interface chipset + (VT82C586), you will want to enable this option to allow use of + bus-mastering DMA data transfers. Read the comments at the beginning of drivers/block/triton.c and Documentation/ide.txt. You can get the latest version of the hdparm utility via ftp (user: anonymous) from sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/; it is - used to tune your harddisk. It is safe to say Y to this question. + used to tune your harddisk. + It is safe to say Y to this question. Other IDE chipset support CONFIG_IDE_CHIPSETS @@ -534,6 +536,19 @@ proxy server). Chances are that you should use this on every machine being run as a router and not on any regular host. If unsure, say N. +SYN flood protection +CONFIG_SYN_COOKIES + Normal TCP/IP networking is open to an attack known as SYN flooding. + This attack prevents legitimate users from being able to connect to + your computer and requires very little work for the attacker. + SYN cookies provide protection against this type of attack. With + this option turned on the TCP/IP stack will use a cryptographic + challenge protocol known as SYN cookies to enable legitimate users + to continue to connect, even when your machine is under attack. + Note that SYN cookies aren't enabled per default, you need to add + echo 1 >/proc/sys/net/ipv4/tcp_syncookies to one of your startup scripts + (e.g. /etc/rc.local or /etc/rc.d/rc.local). + Socket Security API Support (EXPERIMENTAL) CONFIG_NET_SECURITY Enable use of the socket security API. Note that Linux does not include @@ -1324,7 +1339,7 @@ networking available. This feature is experimental. Please see http://www.maths.unm.edu/~bradford/ltpc.html for support software. -LocalTalk PC card support +Apple/Farallon LocalTalk PC card support CONFIG_LTPC This allows you to use the AppleTalk PC card to connect to LocalTalk networks. The card is also known as the Farallon PhoneNet PC card. @@ -1335,6 +1350,26 @@ kernels, so choose Y or N, but not M for now. See README.ltpc in the drivers/net directory, and the web site http://www.math.unm.edu/~bradford/ltpc.html + +COPS LocalTalk PC card support +CONFIG_COPS + This allows you to use the COPS AppleTalk card to connect to LocalTalk + networks. You also need version 1.3.3 or later of the netatalk package. + This driver is experimental, which means that it may not work. + In particular the module support is not yet working for the 2.1.xx + kernels, so choose Y or N, but not M for now. + See the web site http://www.math.unm.edu/~bradford/ltpc.html for localtalk + IP tools. + +Dayna firmware support +CONFIG_COPS_DAYNA + Support COPS compatible cards with Dayna style firmware (Dayna DL2000/ + Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC III) + +Tangent firmware support +CONFIG_COPS_TANGENT + Support COPS compatible cards with Tangent style firmware (Tangent ATB_II, + Novell NL-1000, Daystar Digital LT-200 Amateur Radio AX.25 Level 2 CONFIG_AX25 diff -u --recursive --new-file v2.1.43/linux/Documentation/binfmt_misc.txt linux/Documentation/binfmt_misc.txt --- v2.1.43/linux/Documentation/binfmt_misc.txt Mon Jun 16 16:35:53 1997 +++ linux/Documentation/binfmt_misc.txt Tue Jul 1 08:55:56 1997 @@ -1,5 +1,5 @@ Kernel Support for miscellaneous (your favourite) Binary Formats v1.1 - ==================================================================== + ===================================================================== This Kernel feature allows to invoke almost (for restrictions see below) every program by simply typing it's name in the shell. @@ -47,15 +47,18 @@ - enable Java(TM)-support (like binfmt_java): echo ":Java:M::\xca\xfe\xba\xbe::/usr/local/bin/java:" > register echo :Applet:M::\<\!--applet::/usr/local/bin/appletviewer: > register + - enable support for em86 (like binfmt_em86, for Alpha AXP only): echo ":i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register echo ":i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register + - enable support for packed DOS applications (pre-configured dosemu hdimages): echo ":DEXE:M::\x0eDEX::/usr/bin/dosexec:" > register + - enable support for DOS/Windows executables (using mzloader and dosemu/wine): echo ":DOSWin:M::MZ::/usr/sbin/mzloader:" > register echo ":DOS:E::com::/usr/sbin/mzloader:" > register - + echo ":DOS2:E::exe::/usr/sbin/mzloader:" > register You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable) or 1 (to enable) to /proc/sys/fs/binfmt_misc/status or /proc/.../the_name. @@ -68,13 +71,12 @@ HINTS: ====== -If your interpreter does not look at the PATH to determine the full name of the -program, you need to invoke a wrapper-script (like the following for java) first: +If you want to pass special arguments to your interpreter, you can +write a wrapper script for it. -#!/bin/sh -FOO=`which $1` || exit 1 -shift -/usr/local/bin/java $FOO ${1+$@} +Your interpreter should NOT look in the PATH for the filename; the +kernel passes it the full filename to use. Using the PATH can cause +unexpected behaviour and be a security hazard. There is a web page about binfmt_misc at diff -u --recursive --new-file v2.1.43/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt --- v2.1.43/linux/Documentation/ioctl-number.txt Thu May 15 16:48:01 1997 +++ linux/Documentation/ioctl-number.txt Thu Jun 26 12:33:36 1997 @@ -91,6 +91,7 @@ 'c' all linux/comstats.h 'f' all linux/ext2_fs.h +'k' all asm-sparc/kbio.h, asm-sparc64/kbio.h 'l' 00-3F linux/tcfs_fs.h in development: 'm' all linux/mtio.h conflict! diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/README.cops linux/Documentation/networking/README.cops --- v2.1.43/linux/Documentation/networking/README.cops Wed Dec 31 16:00:00 1969 +++ linux/Documentation/networking/README.cops Thu Jun 26 12:33:36 1997 @@ -0,0 +1,39 @@ +README for the COPS LocalTalk Linux driver (cops.c). + By Jay Schulist + +This driver compiles well against 2.1.29 - 2.1.41. + +Building the driver from the cops-0.0*.tar.gz file. +1. Untar the cops-0.0*.tar.gz it will make a directory called cops. +2. Copy the cops-kernel.diff to /usr/src/ and then type patch -p0 < cops-kernel.diff +3. In the cops driver directory type make install. It will copy the driver to + the linux/drivers/net directory. +4. When you configure your kernel select Y or M for COPS LocalTalk PC support. + Also make sure you have choosen Appletalk support. +5. Compile like usual and you should bet set. + +This driver has 2 modes and they are: Dayna mode and Tangent mode. +Each mode corresponds with the type of card. It has been found +that there are 2 main types of cards and all other cards are +the same and just have different names or only have minor differences +such as more IO ports. As this driver is tested it will +become more clear on exactly what cards are supported. The driver +defaults to using Dayna mode. To change the drivers mode if you build +a driver with dual support use board_type=1 or board_type=2 for +dayna and tangent in the insmod. + +Operation/loading of the driver. +Use modprobe like this: /sbin/modprobe cops.o (IO #) (IRQ #) +If you do not specify any options the driver will try and use the IO = 0x240, +IRQ = 5. As of right now I would only use IRQ 5 for the card, if autoprobing. + +Use ifconfig like this: /sbin/ifconfig lt0 127.0.0.34 up + +You will need to configure atalkd with something like the following to make +it work with the cops.c driver. + +dummy -seed -phase 2 -net 2000 -addr 2000.10 -zone "1033" +lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033" +- Or - +eth0 -seed -phase 2 -net 3000 -addr 3000.20 -zone "1033" +lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033" diff -u --recursive --new-file v2.1.43/linux/Documentation/networking/net-modules.txt linux/Documentation/networking/net-modules.txt --- v2.1.43/linux/Documentation/networking/net-modules.txt Tue May 13 22:41:00 1997 +++ linux/Documentation/networking/net-modules.txt Thu Jun 26 12:33:36 1997 @@ -159,6 +159,13 @@ (Probes ports: 0x378, 0x278, 0x3BC; fixed IRQs: 5 and 7 ) +cops.c: + io = 0x240 + irq = 5 + nodeid = 0 (AutoSelect = 0, NodeID 1-254 is hand selected.) + (Probes ports: 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, + 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360) + de4x5.c: io = 0x000b irq = 10 diff -u --recursive --new-file v2.1.43/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.43/linux/MAINTAINERS Mon Jun 16 16:35:53 1997 +++ linux/MAINTAINERS Thu Jun 26 12:33:36 1997 @@ -260,6 +260,13 @@ L: linux-net@vger.rutgers.edu S: Maintained +MIPS: +P: Ralf Baechle +M: ralf@gnu.ai.mit.edu +W: http://lena.fnet.fr/ +L: linux-mips@fnet.fr +S: Maintained + NCP FILESYSTEM: P: Volker Lendecke M: lendecke@Math.Uni-Goettingen.de diff -u --recursive --new-file v2.1.43/linux/Makefile linux/Makefile --- v2.1.43/linux/Makefile Mon Jun 16 16:35:53 1997 +++ linux/Makefile Thu Jun 26 12:33:36 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 43 +SUBLEVEL = 44 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.43/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.1.43/linux/arch/alpha/defconfig Tue May 13 22:41:00 1997 +++ linux/arch/alpha/defconfig Tue Jul 1 23:23:47 1997 @@ -83,6 +83,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) @@ -194,20 +195,22 @@ # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_DCACHE_PRELOAD is not set +# CONFIG_OMIRR is not set +# CONFIG_TRANS_NAMES is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y -CONFIG_NFS_FS=y -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_FS is not set # CONFIG_NFSD is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set -CONFIG_ISO9660_FS=y +# CONFIG_ISO9660_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set @@ -245,3 +248,4 @@ # Kernel hacking # # CONFIG_PROFILE is not set +# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.1.43/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.43/linux/arch/alpha/kernel/osf_sys.c Mon Jun 16 16:35:53 1997 +++ linux/arch/alpha/kernel/osf_sys.c Tue Jul 1 23:23:47 1997 @@ -295,7 +295,7 @@ retval = verify_area(VERIFY_WRITE, buffer, bufsiz); if (retval) goto out; - retval = namei(NAM_FOLLOW_LINK, path, &inode); + retval = namei(path, &inode); if (retval) goto out; retval = -ENOSYS; @@ -376,7 +376,7 @@ struct file_operations *fops; int retval; - retval = namei(NAM_FOLLOW_LINK, name, &inode); + retval = namei(name, &inode); if (retval) return retval; if (!S_ISBLK(inode->i_mode)) { @@ -876,6 +876,9 @@ return -EOPNOTSUPP; } +/* Dummy functions for now */ +#define wrfpcr(x) do { } while (0) +#define rdfpcr() 0 asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes, diff -u --recursive --new-file v2.1.43/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v2.1.43/linux/arch/i386/boot/compressed/Makefile Wed Apr 16 14:14:59 1997 +++ linux/arch/i386/boot/compressed/Makefile Thu Jun 26 12:33:36 1997 @@ -48,7 +48,7 @@ piggy.o: $(SYSTEM) - tmppiggy=/tmp/$$$$piggy; \ + tmppiggy=_tmp_$$$$piggy; \ rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ $(OBJCOPY) $(SYSTEM) $$tmppiggy; \ gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ diff -u --recursive --new-file v2.1.43/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.43/linux/arch/i386/defconfig Mon Jun 16 16:35:53 1997 +++ linux/arch/i386/defconfig Tue Jul 1 14:21:08 1997 @@ -80,6 +80,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) @@ -194,25 +195,24 @@ # CONFIG_DCACHE_PRELOAD is not set # CONFIG_OMIRR is not set # CONFIG_TRANS_NAMES is not set -CONFIG_MINIX_FS=y +# CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y -CONFIG_NFS_FS=y -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_FS is not set # CONFIG_NFSD is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set -CONFIG_ISO9660_FS=y +# CONFIG_ISO9660_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ROMFS_FS is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set # diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.1.43/linux/arch/i386/kernel/entry.S Tue May 13 22:41:00 1997 +++ linux/arch/i386/kernel/entry.S Thu Jun 26 12:33:36 1997 @@ -526,6 +526,8 @@ .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) - .rept NR_syscalls-169 + .long SYMBOL_NAME(sys_setresgid) /* 170 */ + .long SYMBOL_NAME(sys_getresgid) + .rept NR_syscalls-171 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.43/linux/arch/i386/kernel/irq.c Mon Jun 16 16:35:53 1997 +++ linux/arch/i386/kernel/irq.c Mon Jun 30 15:57:04 1997 @@ -82,12 +82,13 @@ if (irq_nr & 8) { inb(0xA1); /* DUMMY */ outb(cached_A1,0xA1); + outb(0x62,0x20); /* Specific EOI to cascade */ outb(0x20,0xA0); } else { inb(0x21); /* DUMMY */ outb(cached_21,0x21); + outb(0x20,0x20); } - outb(0x20,0x20); spin_unlock(&irq_controller_lock); } @@ -207,7 +208,7 @@ math_error(); } -static struct irqaction irq13 = { math_error_irq, 0, 0, "math error", NULL, NULL }; +static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL }; /* * IRQ2 is cascade interrupt to second interrupt controller diff -u --recursive --new-file v2.1.43/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.1.43/linux/arch/i386/kernel/setup.c Thu May 15 16:48:01 1997 +++ linux/arch/i386/kernel/setup.c Mon Jun 30 15:57:14 1997 @@ -219,7 +219,7 @@ request_region(0x40,0x20,"timer"); request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); - request_region(0xf0,0x10,"npu"); + request_region(0xf0,0x10,"fpu"); } static const char * i486model(unsigned int nr) diff -u --recursive --new-file v2.1.43/linux/arch/m68k/ifpsp060/iskeleton.S linux/arch/m68k/ifpsp060/iskeleton.S --- v2.1.43/linux/arch/m68k/ifpsp060/iskeleton.S Sat May 24 09:10:22 1997 +++ linux/arch/m68k/ifpsp060/iskeleton.S Thu Jun 26 12:33:36 1997 @@ -35,24 +35,7 @@ | #include - -/* - * This has to match entry.S - */ -LOFF_ORIG_D0 = 0x24 - -#define curptr a2 - -#define SAVE_ALL \ - clrl %sp@-; /* stk_adj */ \ - movel %d0,%sp@-; /* orig d0 */ \ - movel %d0,%sp@-; /* d0 */ \ - moveml %d1-%d5/%a0-%a1/%curptr,%sp@-; - -#define GET_CURRENT(tmp) \ - movel %sp,tmp; \ - andw &-8192,tmp; \ - movel tmp,%curptr; +#include |################################ | (1) EXAMPLE CALL-OUTS # @@ -92,9 +75,8 @@ bne Lmustsched rte Lmustsched: - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | indicate stack frame not for syscall + SAVE_ALL_INT + GET_CURRENT(%d0) bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc.. diff -u --recursive --new-file v2.1.43/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.1.43/linux/arch/mips/Makefile Wed Dec 13 02:39:42 1995 +++ linux/arch/mips/Makefile Thu Jun 26 12:33:36 1997 @@ -1,4 +1,6 @@ # +# $Id: Makefile,v 1.5 1997/06/16 00:34:01 ralf Exp $ +# # arch/mips/Makefile # # This file is included by the global makefile so that you can add your own @@ -10,36 +12,33 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1994, 1995 by Ralf Baechle +# Copyright (C) 1994, 1995, 1996 by Ralf Baechle +# DECStation modifications by Paul M. Antoine, 1996 # ifdef CONFIG_CPU_LITTLE_ENDIAN -prefix = mipsel- -oformat = a.out-mips-little-linux +CROSS_COMPILE = mipsel- +ifdef CONFIG_MIPS_ECOFF +oformat = ecoff-littlemips +else +oformat = a.out-mips-big-linux +endif +else +CROSS_COMPILE = mips- +ifdef CONFIG_MIPS_ECOFF +oformat = ecoff-bigmips else -prefix = mips- oformat = a.out-mips-big-linux endif +endif ifdef CONFIG_EXTRA_ELF_COMPILER -prefix := $(prefix)linuxelf- +CROSS_COMPILE := $(CROSS_COMPILE)linuxelf- else -prefix := $(prefix)linux- +CROSS_COMPILE := $(CROSS_COMPILE)linux- endif -AS = $(prefix)as -LD = $(prefix)ld -LINKFLAGS = -N -Ttext 0x80000000 -#LINKFLAGS = -oformat=$(oformat) -N -Ttext 0x80000000 -#HOSTCC = gcc -CC = $(prefix)gcc -D__KERNEL__ -I$(TOPDIR)/include -CPP = $(CC) -E $(CFLAGS) -AR = $(prefix)ar -RANLIB = $(prefix)ranlib -OBJCOPY = $(prefix)objcopy -OBJDUMP = $(prefix)objdump -STRIP = $(prefix)strip -NM = $(prefix)nm +LINKFLAGS = -static -N # # The new ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC @@ -47,46 +46,134 @@ # old GCC these options are just the defaults. At some point we might # make use of global pointer optimizations. # +# The DECStation requires an ECOFF kernel for remote booting, other MIPS +# machines may also. +# ifdef CONFIG_ELF_KERNEL -CFLAGS := $(CFLAGS) -G0 -mno-abicalls -fno-pic -LINKFLAGS += -T arch/mips/ld.script +CFLAGS += -G 0 -mno-abicalls -fno-pic +LINKFLAGS += -G 0 +endif +ifdef CONFIG_ECOFF_KERNEL +CFLAGS += -G 0 -mno-abicalls -fno-pic +LINKFLAGS += -G 0 -oformat ecoff-littlemips endif ifdef CONFIG_REMOTE_DEBUG CFLAGS := $(CFLAGS) -g endif +# +# CPU dependand compiler/assembler options for optimization. +# 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_R4300 +CFLAGS := $(CFLAGS) -mcpu=r4600 -Wa,-mcpu=vr4300 -mips2 endif ifdef CONFIG_CPU_R4X00 -CFLAGS := $(CFLAGS) -D__R4000__ -mcpu=r4400 -mips2 -#ASFLAGS := $(ASFLAGS) -mcpu=r4400 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r4600 -mips2 endif -ifdef CONFIG_CPU_R4600 -CFLAGS := $(CFLAGS) -D__R4000__ -mcpu=r4600 -mips2 -#ASFLAGS := $(ASFLAGS) -mcpu=r4600 -mips2 +ifdef CONFIG_CPU_R5000 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 endif ifdef CONFIG_CPU_R8000 -CFLAGS := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2 -#ASFLAGS := $(ASFLAGS) -mcpu=r8000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 endif ifdef CONFIG_CPU_R10000 -CFLAGS := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2 -#ASFLAGS := $(ASFLAGS) -mcpu=r8000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 +endif + +# +# Board dependand options and extra files +# +ifdef CONFIG_ALGOR_P4032 +CORE_FILES += arch/mips/algor/algor.o +SUBDIRS += arch/mips/algor +#LOADADDR += 0x80000000 +endif +ifdef CONFIG_ACER_PICA_61 +CORE_FILES += arch/mips/jazz/jazz.o +SUBDIRS += arch/mips/jazz +LOADADDR += 0x80000000 +endif +ifdef CONFIG_DECSTATION +CORE_FILES += arch/mips/dec/dec.o +SUBDIRS += arch/mips/dec +LINKSCRIPT += arch/mips/dec/ld.script +LOADADDR += 0x80000000 +endif +ifdef CONFIG_DESKSTATION_RPC44 +CORE_FILES += arch/mips/deskstation/deskstation.o +SUBDIRS += arch/mips/deskstation +LOADADDR += 0x80100000 endif +ifdef CONFIG_DESKSTATION_TYNE +CORE_FILES += arch/mips/deskstation/deskstation.o +SUBDIRS += arch/mips/deskstation +LOADADDR += 0x80000000 +endif +ifdef CONFIG_MIPS_MAGNUM_3000 +LOADADDR += 0x80000000 +endif +ifdef CONFIG_MIPS_MAGNUM_4000 +CORE_FILES += arch/mips/jazz/jazz.o +SUBDIRS += arch/mips/jazz +LOADADDR += 0x80000000 +endif +ifdef CONFIG_OLIVETTI_M700 +CORE_FILES += arch/mips/jazz/jazz.o +SUBDIRS += arch/mips/jazz +LOADADDR += 0x80000000 +endif +ifdef CONFIG_SNI_RM200_PCI +CORE_FILES += arch/mips/sni/sni.o +SUBDIRS += arch/mips/sni +LOADADDR += 0x80000000 +endif +ifdef CONFIG_SGI +LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a +SUBDIRS += arch/mips/sgi/kernel arch/mips/sgi/prom +# +# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, +# 0x88002000 for production kernels. Note that the value must be +# 8kb aligned or the handling of the current variable will break. +# +LOADADDR += 0x88002000 +HOSTCC = cc +endif + +# +# Choosing incompatible machines durings configuration will result in +# error messages during linking. Select a default linkscript if +# none has been choosen above. +# +ifndef LINKSCRIPT +ifndef CONFIG_CPU_LITTLE_ENDIAN +LINKSCRIPT = arch/mips/ld.script.big +else +LINKSCRIPT = arch/mips/ld.script.little +endif +endif +LINKFLAGS += -T $(word 1,$(LINKSCRIPT)) -CFLAGS := $(CFLAGS) -pipe +ifdef LOADADDR +LINKFLAGS += -Ttext $(word 1,$(LOADADDR)) +endif + +# +# The pipe options is bad for my low-mem machine +# Uncomment this if you want this. +# +CFLAGS += -pipe -HEAD := arch/mips/kernel/head.o +HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o -SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib -ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES) +SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools) +CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES) LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot @@ -102,6 +189,7 @@ archclean: @$(MAKEBOOT) clean $(MAKE) -C arch/$(ARCH)/kernel clean + $(MAKE) -C arch/$(ARCH)/tools clean archdep: @$(MAKEBOOT) dep diff -u --recursive --new-file v2.1.43/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.1.43/linux/arch/mips/boot/Makefile Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/boot/Makefile Thu Jun 26 12:33:36 1997 @@ -19,47 +19,32 @@ # 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 a lot. -# This is especially useful 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 +drop-sections = .reginfo .mdebug +strip-flags = $(addprefix --remove-section=,$(drop-sections)) # # 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 +zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux + $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp + ./mkboot zImage.tmp zImage rm -f zImage.tmp - $(STRIP) $(STRIP_FLAGS) zImage -else -zImage: $(CONFIGURE) $(TOPDIR)/vmlinux - cp $(TOPDIR)/vmlinux $@ - $(STRIP) $(STRIP_FLAGS) $@ -endif + +mkboot: mkboot.c + $(HOSTCC) -o $@ $^ zdisk: zImage - mcopy -n zImage a:vmlinux + if [ -f /etc/remote-mcopy ]; then \ + ssh rio mcopy -o - a:vmlinux .depend clean: - rm -f zImage zImage.tmp + rm -f zImage zImage.tmp mkboot dummy: diff -u --recursive --new-file v2.1.43/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c --- v2.1.43/linux/arch/mips/boot/mkboot.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/boot/mkboot.c Thu Jun 26 12:33:36 1997 @@ -0,0 +1,659 @@ +/* + * Make a bootable image from a Linux/MIPS kernel. + * + * 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) 1996 by Ralf Baechle + * + * This file is written in plain Kernighan & Ritchie C as it has to run + * on all crosscompile hosts no matter how braindead. This code might + * also become part of Milo. It's therefore important that we don't use + * seek because the Seek() call of the Magnum 4000 ARC BIOS is broken. + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * Define this for verbose debugging output. + */ +#undef VERBOSE + +/* + * Don't use the host's elf.h - it might be using incompatible defines + */ + +#define EI_NIDENT 16 + +/* + * Basic ELF types. + */ +typedef unsigned short Elf32_Half; +typedef unsigned short Elf32_Section; +typedef unsigned int Elf32_Word; +typedef unsigned int Elf32_Addr; +typedef unsigned int Elf32_Off; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +/* + * ELF magic number + */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ + +#define EI_VERSION 6 /* File version byte index */ +#define EV_CURRENT 1 /* Current version */ + +/* + * Acceptable machine type in e_machine. + */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ + +/* + * The type of ELF file we accept. + */ +#define ET_EXEC 2 /* Executable file */ + +/* + * Definition of a single program header structure + */ +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +/* + * Legal values for p_type + */ +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_NUM 7 /* Number of defined types. */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +/* How to extract and insert information held in the st_info field. */ +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ +#define STB_GLOBAL 1 /* Global symbol */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ + +static unsigned int +get_Elf32_Half(unsigned char *p) +{ + return p[0] | (p[1] << 8); +} +#define get_Elf32_Section(p) get_Elf32_Half(p) + +static unsigned int +get_Elf32_Word(unsigned char *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} +#define get_Elf32_Addr(p) get_Elf32_Word(p) +#define get_Elf32_Off(p) get_Elf32_Word(p) + +static void +put_byte(p, x) + unsigned char *p; + unsigned char x; +{ + p[0] = x; +} + +static void +put_half(p, x) + unsigned char *p; + unsigned short x; +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; +} + +static void +put_word(p, x) + unsigned char *p; + unsigned long x; +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +/* + * Swap a program header in. + */ +static void +get_elfph(p, ph) + unsigned char *p; + Elf32_Phdr *ph; +{ + ph->p_type = get_Elf32_Word(p); + ph->p_offset = get_Elf32_Off(p + 4); + ph->p_vaddr = get_Elf32_Addr(p + 8); + ph->p_paddr = get_Elf32_Addr(p + 12); + ph->p_filesz = get_Elf32_Word(p + 16); + ph->p_memsz = get_Elf32_Word(p + 20); + ph->p_flags = get_Elf32_Word(p + 24); + ph->p_align = get_Elf32_Word(p + 28); +} + +/* + * Swap a section header in. + */ +static void +get_elfsh(p, sh) + unsigned char *p; + Elf32_Shdr *sh; +{ + sh->sh_name = get_Elf32_Word(p); + sh->sh_type = get_Elf32_Word(p + 4); + sh->sh_flags = get_Elf32_Word(p + 8); + sh->sh_addr = get_Elf32_Addr(p + 12); + sh->sh_offset = get_Elf32_Off(p + 16); + sh->sh_size = get_Elf32_Word(p + 20); + sh->sh_link = get_Elf32_Word(p + 24); + sh->sh_info = get_Elf32_Word(p + 28); + sh->sh_addralign = get_Elf32_Word(p + 32); + sh->sh_entsize = get_Elf32_Word(p + 36); +} + +/* + * Swap a section header in. + */ +static void +get_elfsym(p, sym) + unsigned char *p; + Elf32_Sym *sym; +{ + sym->st_name = get_Elf32_Word(p); + sym->st_value = get_Elf32_Addr(p + 4); + sym->st_size = get_Elf32_Word(p + 8); + sym->st_info = *(p + 12); + sym->st_other = *(p + 13); + sym->st_shndx = get_Elf32_Section(p + 14); +} + +/* + * The a.out magic number + */ +#define OMAGIC 0407 /* Code indicating object file or impure executable. */ +#define M_MIPS1 151 /* MIPS R3000/R3000 binary */ +#define M_MIPS2 152 /* MIPS R6000/R4000 binary */ + +/* + * Compute and return an a.out magic number. + */ +#define AOUT_INFO(magic, type, flags) \ + (((magic) & 0xffff) | \ + (((int)(type) & 0xff) << 16) | \ + (((flags) & 0xff) << 24)) + +/* + * a.out symbols + */ +#define N_UNDF 0 +#define N_ABS 2 +#define N_TEXT 4 +#define N_DATA 6 +#define N_BSS 8 +#define N_FN 15 +#define N_EXT 1 + +#define min(x,y) (((x)<(y))?(x):(y)) + +static void +do_read(fd, buf, size) + int fd; + char *buf; + ssize_t size; +{ + ssize_t rd; + + while(size != 0) { + rd = read(fd, buf, size); + if (rd == -1) { + perror("Can't read from file."); + exit(1); + } + size -= rd; + } +} + +static void +writepad(fd, size) + int fd; + size_t size; +{ + static void *zeropage = NULL; + ssize_t written; + + if (zeropage == NULL) { + zeropage = malloc(4096); + if (zeropage == NULL) { + fprintf(stderr, "Couldn't allocate zero buffer.\n"); + exit(1); + } + memset(zeropage, '\0', 4096); + } + while(size != 0) { + written = write(fd, zeropage, min(4096, size)); + if (written == -1) { + perror("Can't write to boot image"); + exit(1); + } + size -= written; + } +} + +static void +do_write(fd, buf, size) + int fd; + char *buf; + ssize_t size; +{ + ssize_t written; + + while(size != 0) { + written = write(fd, buf, size); + if (written == -1) { + perror("Can't write to boot image"); + exit(1); + } + size -= written; + } +} + +static int +usage(program_name) + char *program_name; +{ + fprintf(stderr, "Usage: %s infile outfile\n", program_name); + exit(0); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char *infile, *outfile; + struct stat ifstat; + off_t ifsize; + char *image; + int ifd, ofd, i, symtabix, strtabix; + Elf32_Ehdr eh; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + unsigned long vaddr, entry, bss, kernel_entry, kernel_end; + unsigned char ahdr[32]; + Elf32_Sym sym; + int symnum; + char *symname; + + /* + * Verify some basic assuptions about type sizes made in this code + */ + if (sizeof(Elf32_Half) != 2) { + fprintf(stderr, "Fix mkboot: sizeof(Elf32_Half) != 2\n"); + exit(1); + } + if (sizeof(Elf32_Word) != 4) { + fprintf(stderr, "Fix mkboot: sizeof(Elf32_Word) != 4\n"); + exit(1); + } + if (sizeof(Elf32_Addr) != 4) { + fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n"); + exit(1); + } + + if (argc != 3) + usage(argv[0]); + + infile = argv[1]; + outfile = argv[2]; + + if (stat(infile, &ifstat) < 0) { + perror("Can't stat kernel image."); + exit(1); + } + + if (!S_ISREG(ifstat.st_mode)) { + fprintf(stderr, "Input file isn't a regular file.\n"); + exit(1); + } + ifsize = ifstat.st_size; + + image = malloc((size_t)ifsize); + if (image == NULL) { + fprintf(stderr, "Can't allocate memory to read file\n"); + exit(1); + } + + /* + * Read the entire input file in. + */ + ifd = open(infile, O_RDONLY); + if(ifd == 0) { + fprintf(stderr, "Can't open input file\n"); + exit(1); + } + do_read(ifd, image, ifsize); + close(ifd); + + /* + * Now swap the ELF header in. This is ugly but we the file + * we're reading might have different type sizes, byteorder + * or alignment than the host. + */ + memcpy(eh.e_ident, (void *)image, sizeof(eh.e_ident)); + if(memcmp(eh.e_ident, ELFMAG, SELFMAG)) { + fprintf(stderr, "Input file isn't a ELF file\n"); + exit(1); + } + if(eh.e_ident[EI_CLASS] != ELFCLASS32) { + fprintf(stderr, "Input file isn't a 32 bit ELF file\n"); + exit(1); + } + if(eh.e_ident[EI_DATA] != ELFDATA2LSB) { + fprintf(stderr, "Input file isn't a little endian ELF file\n"); + exit(1); + } + if(eh.e_ident[EI_VERSION] != EV_CURRENT) { + fprintf(stderr, "Input file isn't a version %d ELF file\n", + EV_CURRENT); + exit(1); + } + + /* + * Ok, so far the file looks ok. Now swap the rest of the header in + * and do some more paranoia checks. + */ + eh.e_type = get_Elf32_Half(image + 16); + eh.e_machine = get_Elf32_Half(image + 18); + eh.e_version = get_Elf32_Word(image + 20); + eh.e_entry = get_Elf32_Addr(image + 24); + eh.e_phoff = get_Elf32_Off(image + 28); + eh.e_shoff = get_Elf32_Off(image + 32); + eh.e_flags = get_Elf32_Word(image + 36); + eh.e_ehsize = get_Elf32_Half(image + 40); + eh.e_phentsize = get_Elf32_Half(image + 42); + eh.e_phnum = get_Elf32_Half(image + 44); + eh.e_shentsize = get_Elf32_Half(image + 46); + eh.e_shnum = get_Elf32_Half(image + 48); + eh.e_shstrndx = get_Elf32_Half(image + 50); + + if(eh.e_type != ET_EXEC) { + fprintf(stderr, "Input file isn't a executable.\n"); + exit(1); + } + if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) { + fprintf(stderr, "Input file isn't a MIPS executable.\n"); + exit(1); + } + + /* + * Now read the program headers ... + */ + ph = malloc(sizeof(Elf32_Phdr) * eh.e_phnum); + if (ph == NULL) { + fprintf(stderr, "No memory for program header table.\n"); + exit(1); + } + for(i = 0;i < eh.e_phnum; i++) + get_elfph((void *)(image + eh.e_phoff + i * 32), ph + i); + + /* + * ... and then the section headers. + */ + sh = malloc(sizeof(Elf32_Shdr) * eh.e_shnum); + if (sh == NULL) { + fprintf(stderr, "No memory for section header table.\n"); + exit(1); + } + for(i = 0;i < eh.e_shnum; i++) + get_elfsh((void *)(image + eh.e_shoff + (i * 40)), sh + i); + + /* + * Find the symboltable and the stringtable in the file. + */ + for(i = 0;i < eh.e_shnum; i++) { + if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, + ".symtab")) { + symtabix = i; + continue; + } + if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, + ".strtab")) { + strtabix = i; + continue; + } + } + + if (symtabix == -1) { + fprintf(stderr, "The executable doesn't have a symbol table\n"); + exit(1); + } + if (strtabix == -1) { + fprintf(stderr, "The executable doesn't have a string table\n"); + exit(1); + } + + /* + * Dig for the two required symbols in the symbol table. + */ + symnum = sh[symtabix].sh_size / 16; + for(i = 0;i < symnum;i++) { + get_elfsym(image + sh[symtabix].sh_offset + (i * 16), &sym); + symname = image + sh[strtabix].sh_offset + sym.st_name; + if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) + continue; + if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE && + ELF32_ST_TYPE(sym.st_info) != STT_OBJECT && + ELF32_ST_TYPE(sym.st_info) != STT_FUNC) + continue; + if (strcmp("kernel_entry", symname) == 0) { + kernel_entry = sym.st_value; + continue; + } + if (strcmp("_end", symname) == 0) { + kernel_end = sym.st_value; + continue; + } + } + +#ifdef VERBOSE + /* + * And print what we will be loaded into memory. + */ + for(i = 0;i < eh.e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) { + continue; + } + printf(" Offset: %08lx\n", ph[i].p_offset); + printf(" file size: %08lx\n", ph[i].p_filesz); + printf(" mem size: %08lx\n", ph[i].p_memsz); + printf(" Loading: %08lx - %08lx\n", + ph[i].p_vaddr, ph[i].p_vaddr + ph[i].p_filesz); + printf(" Zero mapping: %08lx - %08lx\n", + ph[i].p_vaddr + ph[i].p_filesz, + ph[i].p_vaddr + ph[i].p_memsz); + } +#endif + + /* + * Time to open the outputfile. + */ + ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (ofd == -1) { + perror("Can't open boot image for output."); + exit(1); + } + + /* + * First compute the layout of the file. We need to do this + * first because we can't seek back to the beginning due to the + * broken Seek() call in the Magnum firmware. + */ + entry = vaddr = 0xffffffff; + bss = 0; + for(i = 0;i < eh.e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) + continue; + if (vaddr == 0xffffffff) + entry = vaddr = ph[i].p_vaddr; + vaddr = ph[i].p_vaddr + ph[i].p_filesz; + bss = ph[i].p_memsz - ph[i].p_filesz; + } + + /* + * In the next step we construct the boot image. The boot file + * looks essentially like a dump of the loaded kernel with a + * minimal header. Because Milo supports already a.out image + * we simply dump the image in an a.out image ... First let's + * write the header. + */ + + /* + * Create and write the a.out header. + */ + put_word(ahdr, AOUT_INFO(OMAGIC, M_MIPS1, 0)); + put_word(ahdr + 4, vaddr - entry); /* text size */ + put_word(ahdr + 8, 0); /* data size */ + put_word(ahdr + 12, bss); /* bss size */ + put_word(ahdr + 16, 2 * 12); /* size of symbol table */ + put_word(ahdr + 20, entry); /* base address */ + put_word(ahdr + 24, 0); /* size of text relocations */ + put_word(ahdr + 28, 0); /* size of data relocations */ + do_write(ofd, ahdr, 32); + + /* + * Write text and data segment combined into the a.out text segment + * and a zero length data segment into the file. + */ + vaddr = 0xffffffff; + bss = 0; + for(i = 0;i < eh.e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) + continue; + if (vaddr == 0xffffffff) + vaddr = ph[i].p_vaddr; + writepad(ofd, ph[i].p_vaddr - vaddr); /* Write zero pad */ + do_write(ofd, image + ph[i].p_offset, ph[i].p_filesz); + vaddr = ph[i].p_vaddr + ph[i].p_filesz; + bss = ph[i].p_memsz - ph[i].p_filesz; + } + + /* + * Now write the symbol table. It has only two symbols, + * kernel_entry and _end which we need for booting. + */ + put_word(ahdr , 4); /* n_un.n_strx */ + put_byte(ahdr + 4, N_TEXT | N_EXT); /* n_type */ + put_byte(ahdr + 5, 0); /* n_other */ + put_half(ahdr + 6, 0); /* n_desc */ + put_word(ahdr + 8, kernel_entry); /* n_value */ + do_write(ofd, ahdr, 12); + + put_word(ahdr , 4 + 13); /* n_un.n_strx */ + put_byte(ahdr + 4, N_ABS | N_EXT); /* n_type */ + put_byte(ahdr + 5, 0); /* n_other */ + put_half(ahdr + 6, 0); /* n_desc */ + put_word(ahdr + 8, kernel_end); /* n_value */ + do_write(ofd, ahdr, 12); + + /* + * Now write stringtable size and the strings. + */ + put_word(ahdr, 4 + 20); + do_write(ofd, ahdr, 4); + do_write(ofd, "kernel_entry\0_end\0\0", 20); + + /* + * That's is all ... + */ + close(ofd); + +#ifdef VERBOSE + printf("Entry: %08lx\n", entry); + printf("Dumped image %08lx - %08lx\n", 0x80000000, vaddr); + printf("Extra bss at end: %08lx\n", bss); +#endif + + return 0; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.1.43/linux/arch/mips/config.in Mon Apr 7 11:35:29 1997 +++ linux/arch/mips/config.in Thu Jun 26 12:33:36 1997 @@ -3,62 +3,102 @@ # see the Configure script. # mainmenu_name "Linux Kernel Configuration" - + mainmenu_option next_comment -comment 'Machine setup' +comment 'Code maturity level options' +bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +endmenu +mainmenu_option next_comment +comment 'Machine selection' 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 +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032 + 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 +fi bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000 -bool 'Support for Olivetti M700' CONFIG_OLIVETTI_M700 -if [ "$CONFIG_ACER_PICA_61" = "y" -o \ - "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ +bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 +if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then + define_bool CONFIG_VIDEO_G364 y +fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Support for SGI workstations' CONFIG_SGI +fi +bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI +if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \ + "$CONFIG_DESKSTATION_TYNE" = "y" ]; then + define_bool CONFIG_MIPS_ARC y +fi +if [ "$CONFIG_ACER_PICA_61" = "y" -o \ + "$CONFIG_OLIVETTI_M700" = "y" -o \ + "$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then define_bool CONFIG_MIPS_JAZZ y fi +unset CONFIG_PCI +if [ "$CONFIG_SNI_RM200_PCI" = "y" -o \ + "$CONFIG_ALGOR_P4032" = "y" ]; then + define_bool CONFIG_PCI y +fi +endmenu + +mainmenu_option next_comment +comment 'CPU selection' choice 'CPU type' \ "R3000 CONFIG_CPU_R3000 \ R6000 CONFIG_CPU_R6000 \ + R4300 CONFIG_CPU_R4300 \ R4x00 CONFIG_CPU_R4X00 \ - R4600 CONFIG_CPU_R4600 \ + R5000 CONFIG_CPU_R5000 \ 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 +endmenu +mainmenu_option next_comment +comment 'General setup' +if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL + define_bool CONFIG_CPU_LITTLE_ENDIAN y +else + define_bool CONFIG_ELF_KERNEL y + bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN +fi +if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then + define_bool CONFIG_BINFMT_IRIX y +fi define_bool CONFIG_BINFMT_ELF y -define_bool CONFIG_BINFMT_AOUT 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 +define_bool CONFIG_BINFMT_AOUT n +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA 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 -# if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -# bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE -# fi -#fi bool 'System V IPC' CONFIG_SYSVIPC bool 'Sysctl support' CONFIG_SYSCTL + +if [ "$CONFIG_SGI" != "y" ]; then + tristate 'Parallel port support' CONFIG_PNP_PARPORT +fi + endmenu mainmenu_option next_comment comment 'Loadable module support' -bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS -endmenu +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD +fi -source drivers/block/Config.in +# +# All SGI block devices are SCSI based AFAIK. -davem +# +if [ "$CONFIG_SGI" != "y" ]; then + source drivers/block/Config.in +fi if [ "$CONFIG_NET" = "y" ]; then source net/Config.in @@ -70,7 +110,27 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - source drivers/scsi/Config.in + if [ "$CONFIG_SGI" = "y" ]; then + comment 'SCSI support type (disk, tape, CDrom)' + + dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI + dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI + dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI + dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI + + comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' + + bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN + + bool 'Verbose SCSI error reporting' CONFIG_SCSI_CONSTANTS + + #mainmenu_option next_comment + comment 'SCSI low-level drivers' + + dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI + else + source drivers/scsi/Config.in + fi fi endmenu @@ -80,38 +140,76 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - source drivers/net/Config.in + if [ "$CONFIG_SGI" != "y" ]; then + source drivers/net/Config.in + else + tristate 'Dummy net driver support' CONFIG_DUMMY + tristate 'SLIP (serial line) support' CONFIG_SLIP + if [ "$CONFIG_SLIP" != "n" ]; then + bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED + bool ' Keepalive and linefill' CONFIG_SLIP_SMART + fi + tristate 'PPP (point-to-point) support' CONFIG_PPP + if [ ! "$CONFIG_PPP" = "n" ]; then + comment 'CCP compressors for PPP are only built as modules.' + fi + bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ + fi fi endmenu fi -mainmenu_option next_comment -comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)' - -bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI -if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then - source drivers/cdrom/Config.in +if [ "$CONFIG_SGI" != "y" ]; then + mainmenu_option next_comment + comment 'ISDN subsystem' + + tristate 'ISDN support' CONFIG_ISDN + if [ "$CONFIG_ISDN" != "n" ]; then + source drivers/isdn/Config.in + fi + endmenu + + mainmenu_option next_comment + comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)' + + bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI + if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then + source drivers/cdrom/Config.in + fi + endmenu fi -endmenu source fs/Config.in -source drivers/char/Config.in -bool 'Standard serial device support' CONFIG_SERIAL n +if [ "$CONFIG_SGI" != "y" ]; then + source drivers/char/Config.in -mainmenu_option next_comment -comment 'Sound' + mainmenu_option next_comment + comment 'Sound' -tristate 'Sound card support' CONFIG_SOUND -if [ "$CONFIG_SOUND" != "n" ]; then - source drivers/sound/Config.in + tristate 'Sound card support' CONFIG_SOUND + if [ "$CONFIG_SOUND" != "n" ]; then + source drivers/sound/Config.in + fi + endmenu +else + comment 'SGI Character Devices' + bool 'Virtual terminal' CONFIG_VT + if [ "$CONFIG_VT" = "y" ]; then + bool 'Console on virtual terminal' CONFIG_VT_CONSOLE + fi + tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE + bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL + if [ "$CONFIG_SGI_SERIAL" != "n" ]; then + define_bool CONFIG_SERIAL y + fi fi -endmenu mainmenu_option next_comment comment 'Kernel hacking' #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC +bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG bool 'Kernel profiling support' CONFIG_PROFILE if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile --- v2.1.43/linux/arch/mips/dec/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/Makefile Thu Jun 26 12:33:36 1997 @@ -0,0 +1,24 @@ +# +# Makefile for the DECstation family specific parts of the 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: dec.o +O_TARGET := dec.o +O_OBJS := boot.o int-handler.o decstation.o hw-access.o reset.o setup.o + +boot.o: boot.S + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/boot.S linux/arch/mips/dec/boot.S --- v2.1.43/linux/arch/mips/dec/boot.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/boot.S Thu Jun 26 12:33:36 1997 @@ -0,0 +1,92 @@ +/* + * arch/mips/dec/boot.S + * + * Copyright (C) 1995, 1996 Paul M. Antoine + * + * Written by Ralf Baechle and Andreas Busse, modified for DECStation + * support by Paul Antoine. + * + * NOTE: There are references to R4X00 code in here, because there is an + * upgrade module for Personal DECStations with such a CPU! + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * dec_entry: Called by the boot PROM loader to do DECStation setup, prior + * to calling dec_setup() to fill in the boot_info structure. + * + * This code should also go in the boot loader for loading off + * floppy and HD... in addition to the tags code in dec_setup(). + * + * FIXME: arrange for this code only to be linked in when building a + * kernel image to be booted via tftp from the boot prom?? + */ + .text + .globl dec_entry +dec_entry: + /* Save the address of the REX call vector for later + * use in printing debug messages. + */ + sw a3,pmax_rex_base + sw a2,rex_prom_magic + la a0,dec_signon + jal pmax_printf + nop + + /* Now set up the bootinfo with things that + * should be loaded by the boot loader, except that + * for the moment we're booting using tftp. + */ + jal dec_setup + nop +/* + * Now we need to move exception vector handler routines that appear + * in head.S down to the right addresses, 'cos the DECStation loads + * kernels at 0x80030000... + */ + +/* + * First move the TLB refill code down to offset 0x000, at addr 0x80000000 + */ + la t0,except_vec0 # begining of exception code + la t1,except_vec1 # end of exception code + la t2,0x80000000 # where the code should live + lw t3,(t0) # get first word +1: sw t3,(t2) # put it where it should go + addiu t0,4 # increment both pointers + addiu t2,4 + lw t3,(t0) # will be in the delay slot + bne t0,t1,1b +/* + * Now move the General Exception code down to offset 0x080 at 0x80000000 + */ + la t0,except_vec3 # begining of general exception code + la t1,end_except # end of general exception code + la t2,0x80000080 # where the code should live + lw t3,(t0) # get first word +1: sw t3,(t2) + addiu t0,4 + addiu t2,4 + lw t3,(t0) + bne t0,t1,1b + + la a0,dec_launch # say where we are going + jal pmax_printf + nop + + la t0,mach_mem_upper # get upper memory bound + lw a0,(t0) + j kernel_entry + nop + + .data + .align 2 +dec_signon: .ascii "\n\nLinux/MIPS DECStation Boot\n"; + .asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n"; +dec_launch: .asciiz "Setup complete, launching kernel...\n"; diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/decstation.S linux/arch/mips/dec/decstation.S --- v2.1.43/linux/arch/mips/dec/decstation.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/decstation.S Thu Jun 26 12:33:36 1997 @@ -0,0 +1,369 @@ +/* + * arch/mips/kernel/decstation.S + * + * Copyright (C) 1995, 1996 Paul M. Antoine + * + * Written by Ralf Baechle and Andreas Busse, modified for DECStation + * support by Paul Antoine. + * + * NOTE: There are references to R4X00 code in here, because I believe + * that there is an upgrade module for Personal DECStations with + * such CPU's! + * + * FIXME: still plenty to do in this file, as much of the code towards + * the end hasn't been modified to suit the DECStation's interrupts. + * (Paul, you need to fix this file to comply with NAPS. Won't be + * too hard - Ralf) + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * dec_entry: Called at boot in head.S to do DECStation setup, and to + * fill in the boot_info structure. + */ + .text + .globl dec_entry +dec_entry: + /* Save the address of the REX call vector for later + * use in printing debug messages. + */ + sw a3,pmax_rex_base + la a0,dec_signon + jal pmax_printf + nop + /* Now set up the bootinfo structure with things that + * should be loaded by the boot loader, except that + * for the moment we're booting using tftp. + */ + la t0,boot_info + li t1,0x40 # 64 TLB entries +/* + * FIXME: Ideally, all DEC workstations should be supported, so here we + * should put some clevernesses to determine machine type and CPU + * type. Needs a hierarchy of DEC machine types. Perhaps Machine + * AND Model fields in bootinfo structure? + */ + sw t1,OFFSET_BOOTINFO_TLB_ENTRIES(t0) + li t1,MACH_DECSTATION # Machine type + sw t1,(t0) + li t1,CPU_R3000A # CPU type + sw t1,OFFSET_BOOTINFO_CPUTYPE(t0) +/* + * FIXME: the following should find the memory size from the boot PROM + */ + li t1,0x80000000 # Lower memory bound + sw t1,OFFSET_BOOTINFO_MEMLOWER(t0) + li t1,0x88000000 # Upper memory bound (8MB) + sw t1,OFFSET_BOOTINFO_MEMUPPER(t0) +/* + * FIXME: the following should determine the cache size a la the method + * used in MACH. For now we just guess - PMA. + */ + li t1,0x100000 # 64K icache + sw t1,OFFSET_BOOTINFO_ICACHE_SIZE(t0) + li t1,0x100000 # 64K dcache + sw t1,OFFSET_BOOTINFO_DCACHE_SIZE(t0) + +/* + * FIXME: template for other bootinfo fields that probably need filling in... + * + li t1,0x80000000 + sw t1,OFFSET_BOOTINFO_(t0) +*/ + +/* + * Now we need to move exception vector handler routines that appear + * in head.S down to the right addresses, 'cos the DECStation loads + * kernels at 0x80030000... + */ + +/* + * First move the TLB refill code down to offset 0x000, at addr 0x80000000 + */ + la t0,except_vec0 # begining of TLB exception code + la t1,except_vec1 # end of TLB exception code + la t2,0x80000000 # where the code should live + lw t3,(t0) # get first word +1: sw t3,(t2) # put it where it should go + addiu t0,4 # increment both pointers + addiu t2,4 + lw t3,(t0) # will be in the delay slot + bne t0,t1,1b + +/* + * Now move the General Exception code down to offset 0x080 at 0x80000000 + */ + la t0,except_vec3 # begining of general exception code + la t1,kernel_entry # end of general exception code + la t2,0x80000080 # where the code should live + lw t3,(t0) # get first word +1: sw t3,(t2) + addiu t0,4 + addiu t2,4 + lw t3,(t0) + bne t0,t1,1b + +/* + * FIXME: Don't forget to set the gp regster... why do I need this? + */ + la gp,_gp + la a0,dec_launch # say where we are going + jal pmax_printf + nop + j kernel_entry + nop + + .data + .align 2 +dec_signon: .ascii "\n\nLinux/MIPS DECStation Boot\n"; + .asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n"; +dec_launch: .asciiz "Launching kernel...\n"; + .text + .set noreorder +/* + * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x + * + * FIXME: this is *extremely* experimental, though it is probably o.k. for + * most DECStation models. + */ + NESTED(decstation_handle_int, FR_SIZE, ra) + .set noat + SAVE_ALL + REG_S sp,FR_ORIG_REG2(sp) + 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 +/* + * FIXME: The following branch was: + * beqz t0,spurious_interrupt + * + * ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 ) + * to complain: + * + * "Can not represent relocation in this object file format"... + * + * hence this hack to branch foward a bit, and then jump + * Perhaps a later version of gas will cope? - Paul + * (No, this is impossible in COFF as well as in ELF. - Ralf) + */ + beqz t0,3f; + 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 + */ + .set reorder +2: LOAD_L t0,(t1) + jr t0 + .set noreorder + END(decstation_handle_int) + +/* + * FIXME: The hack mentioned above. + */ +3: j spurious_interrupt + nop + +/* + * FIXME: the rest of this is pretty suspect, as it's straight from + * jazz.S... and I really haven't altered it at all - Paul + */ + +/* + * Used for keyboard driver's fake_keyboard_interrupt() + * (Paul, even for i386 this is no longer being used -- Ralf) + */ +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") + +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") + +/* + * Ethernet interrupt, remapped to level 15 + * NOTE: Due to a bug somewhere in the kernel I was not able + * to figure out, the PRINT() is necessary. Without this, + * I get a "gfp called nonatomically from interrupt 00000000". + * Only god knows why... Tell me if you find the reason! + * (You were fouled by the caches and this is the wrong file for this + * comment - Ralf) + * Andy, 6/16/95 + */ +loc_ethernet: PANIC("Unimplemented loc_ethernet\n") + +/* + * Keyboard interrupt, remapped to level 1 + */ +loc_keyboard: PANIC("Unimplemented loc_keyboard\n") + +loc_mouse: PANIC("Unimplemented loc_mouse handler") + +/* + * Serial port 1 IRQ, remapped to level 3 + */ +loc_serial1: PANIC("Unimplemented loc_serial handler") + +/* + * Serial port 2 IRQ, remapped to level 4 + */ +loc_serial2: PANIC("Unimplemented loc_serial handler") + +/* + * Parallel port IRQ, remapped to level 5 + */ +loc_parallel: PANIC("Unimplemented loc_parallel handler") + +/* + * Floppy IRQ, remapped to level 6 + */ +loc_floppy: PANIC("Unimplemented loc_floppy handler") + +/* + * Now call the real handler + */ +loc_call: la t0,IRQ_vectors # delay slot + + /* + * Temporarily disable interrupt source + */ +/* lhu t2,JAZZ_IO_IRQ_ENABLE +*/ + addu t0,t3 # make ptr to IRQ handler + LOAD_L 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 */ + or t2,s1 +/* sh t2,JAZZ_IO_IRQ_ENABLE */ + + jr v0 + nop # delay slot + +ll_tc3: PANIC("Unimplemented tc3 interrupt handler") + +ll_fpu: PANIC("Unimplemented fpu interrupt handler") + +ll_io_error: PANIC("Unimplemented I/O write timeout interrupt handler") + +ll_rtc: PANIC("Unimplemented RTC interrupt handler") + +/* + * Timer IRQ + * We remap the timer irq to be more similar to a IBM compatible + */ +ll_timer: PANIC("Timer interrupt!\n"); +/* + * CPU count/compare IRQ (unused) + */ +ll_reset: li a0,0 + jal pmax_halt + li a1,0 # delay slot + +/* + * Now call the real handler + */ +call_real: la t0,IRQ_vectors # delay slot + + /* + * temporarily disable interrupt + */ + mfc0 t2,CP0_STATUS + and t2,s1 + + addu t0,t3 + LOAD_L 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 + + jr v0 + nop # delay slot + +/* + * Just for debugging... load a0 with address of the point inside the + * framebuffer at which you want to draw a line of 16x32 pixels. + * Maxine's framebuffer starts at 0xaa000000. + */ + .set reorder + LEAF(drawline) + li t1,0xffffffff # set all pixels on + li t2,0x10 # we will write 16 words +1: sw t1,(a0) # write the first word + addiu a0,a0,4 # move our framebuffer pointer + addiu t2,t2,-1 # one less to do + bnez t2,1b # finished? + jr ra + END(drawline) + +/* + * FIXME: I have begun to alter this table to reflect Personal DECStation + * (i.e. Maxine) interrupts... Paul. + */ + .data + PTR ll_sw0 # SW0 + PTR ll_sw1 # SW1 + PTR ll_timer # Periodic interrupt + PTR ll_rtc # RTC periodic interrupt + PTR ll_io_error # Timeout on I/O writes + PTR ll_tc3 # TC slot 3, motherboard + PTR ll_reset # Halt keycode (CTRL+ALT+ENTER) +ll_vectors: PTR ll_fpu # FPU + +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 diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/decstation.c linux/arch/mips/dec/decstation.c --- v2.1.43/linux/arch/mips/dec/decstation.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/decstation.c Thu Jun 26 12:33:36 1997 @@ -0,0 +1,200 @@ +/* + * arch/mips/dec/decstation.c + * + * Copyright (C) 1996 Paul M. Antoine + * + * Written by Paul Antoine. + * + * FIXME: still plenty to do in this file, as we don't yet fully fill + * the boot info structure with DEC-specific tags. Also still + * too specific to the Person Decstattion 5000/2x!! + */ + +#include +#include /* FIXME: what about other decstations? */ +#include + +/* + * dec_setup: Called at boot from dec_entry() in boot.S to do + * DECStation-specific setup, and to fill in the kernel argument + * tags. + * + * FIXME: I'm not sure all DEC workstations are correctly supported. This + * code may not need to be here when booting off floppy or HD?? + */ + +unsigned long mach_mem_upper = 0; +unsigned long mach_mem_lower = 0; +unsigned long mips_dcache_size = 0; +unsigned long mips_icache_size = 0; +unsigned long rex_prom_magic; /* from boot.S */ +unsigned long dec_get_memory_size(void); + +void dec_setup(void) +{ + unsigned long int mem_mask = 0; + unsigned long tag_data_dummy, dec_sysid; + unsigned char dec_cpunum, dec_systype, dec_firmrev, dec_etc; + extern const char *linux_banner; + + pmax_printf("%s\n", linux_banner); + /* First we need the memory upper bound before we can add tag entries... */ + mach_mem_lower = 0x80000000L; + mach_mem_upper = mach_mem_lower + dec_get_memory_size(); + + /* First tag is always memory upper limit, right Stoned?? */ + (void)bi_TagAdd(tag_memupper, ULONGSIZE, &mach_mem_upper); + + /* We're obviously one of the DEC machines */ + tag_data_dummy = MACH_GROUP_DEC; + (void)bi_TagAdd(tag_machgroup, ULONGSIZE, &tag_data_dummy); + + /* Now let's try to figure out what type of DECStation we are */ + pmax_printf("System id is: "); + if ((dec_sysid = pmax_getsysid()) != 0) + pmax_printf("%x\n", dec_sysid); + else + pmax_printf("unknown\n"); + + dec_cpunum = (dec_sysid & 0xff000000) >> 24; + dec_systype = (dec_sysid & 0xff0000) >> 16; + dec_firmrev = (dec_sysid & 0xff00) >> 8; + dec_etc = dec_sysid & 0xff; + + /* + * FIXME: for now use the PROM to determine the CPU type - should + * probably just get the CPU to tell us. + */ + pmax_printf("System has an "); + switch(dec_cpunum) + { + case 0x82: + { + pmax_printf("R3000 CPU\n"); + tag_data_dummy = CPU_R3000A; + break; + } + case 0x84: + { + pmax_printf("R4000 CPU\n"); + /* FIXME: assume a plain R4000PC for now */ + tag_data_dummy = CPU_R4000PC; + break; + } + default: + { + pmax_printf("unknown CPU, code is %x\n", dec_cpunum); + /* FIXME: assume an R2000 for now */ + tag_data_dummy = CPU_R2000; + break; + } + } + /* Add the CPU type */ + (void)bi_TagAdd(tag_cputype, ULONGSIZE, &tag_data_dummy); + + pmax_printf("System has firmware type: "); + if (dec_firmrev == 2) + pmax_printf("TCF0\n"); + else + pmax_printf("TCF1\n"); + + pmax_printf("This DECStation is a: "); + switch(dec_systype) { + case 1: /* DS2100/3100 Pmax */ + pmax_printf("DS2100/3100\n"); + tag_data_dummy = MACH_DECSTATION; + break; + case 2: /* DS5000 3max */ + pmax_printf("DS5000\n"); + tag_data_dummy = MACH_DECSTATION; + break; + case 3: /* DS5000/100 3min */ + pmax_printf("DS5000/1x0\n"); + tag_data_dummy = MACH_DECSTATION; + break; + case 7: /* Personal DS5000/2x */ + pmax_printf("Personal DS5000/2x\n"); + tag_data_dummy = MACH_DECSTATION; + break; + default: + pmax_printf("unknown, id is: %x\n", dec_systype); + tag_data_dummy = MACH_UNKNOWN; + break; + } + + /* Add the machine type */ + (void)bi_TagAdd(tag_machtype, ULONGSIZE, &tag_data_dummy); + + /* Add the number of tlb entries */ + tag_data_dummy = 64; + (void)bi_TagAdd(tag_tlb_entries, ULONGSIZE, &tag_data_dummy); + + /* + * Add the instruction cache size + * FIXME: should determine this somehow + */ + tag_data_dummy = 0x100000; /* set it to 64K for now */ + (void)bi_TagAdd(tag_icache_size, ULONGSIZE, &tag_data_dummy); + mips_icache_size = tag_data_dummy; + + /* + * Add the data cache size + * FIXME: should determine this somehow + */ + tag_data_dummy = 0x100000; /* set it to 64K for now */ + (void)bi_TagAdd(tag_dcache_size, ULONGSIZE, &tag_data_dummy); + mips_dcache_size = tag_data_dummy; + + /* FIXME: should determine vram_base properly */ + tag_data_dummy = 0xa8000000; + (void)bi_TagAdd(tag_vram_base, ULONGSIZE, &tag_data_dummy); + + /* FIXME: dummy drive info tag */ + tag_data_dummy = 0; + (void)bi_TagAdd(tag_drive_info, ULONGSIZE, &tag_data_dummy); + + /* FIXME: do we need a dummy tag at the end? */ + tag_data_dummy = 0; + (void)bi_TagAdd(tag_dummy, 0, &tag_data_dummy); + + pmax_printf("Added tags\n"); +} /* dec_setup */ + +unsigned long dec_get_memory_size() +{ + int i, bitmap_size; + unsigned long mem_size = 0; + struct pmax_bitmap { + int pagesize; + unsigned char bitmap[64*1024*1024 - 4]; + } *bm; + + /* some free 64k */ + bm = (struct pmax_bitmap *)0x8002f000; + bitmap_size = pmax_getbitmap(bm); + + pmax_printf("Page size is: %x\n", bm->pagesize); + pmax_printf("Bitmap size is: %d bytes\n", bitmap_size); + + for (i = 0; i < bitmap_size; i++) + { + /* FIXME: very simplistically only add full sets of pages */ + if (bm->bitmap[i] == 0xff) + mem_size += (8 * bm->pagesize); + } + pmax_printf("Main memory size is: %d KB\n", (mem_size / 1024)); + return(mem_size); +} /* dec_get_memory_size */ + +unsigned char maxine_rtc_read_data(unsigned long addr) +{ + char *rtc = (char *)(PMAX_RTC_BASE); + return(rtc[addr * 4]); +} /* maxine_rtc_read_data */ + +void maxine_rtc_write_data(unsigned char data, unsigned long addr) +{ + char *rtc = (char *)(PMAX_RTC_BASE); + rtc[addr * 4] = data; +} /* maxine_rtc_read_data */ + diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/hw-access.c linux/arch/mips/dec/hw-access.c --- v2.1.43/linux/arch/mips/dec/hw-access.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/hw-access.c Thu Jun 26 12:33:36 1997 @@ -0,0 +1,26 @@ +/* + * DECstation specific hardware access code. + * + * 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) 1996 by Paul Antoine + */ +#include +#include +#include +#include + +asmlinkage void decstation_handle_int(void); +extern unsigned char maxine_rtc_read_data(unsigned long); +extern void maxine_rtc_write_data(unsigned char, unsigned long); + +/* + * FIXME: Don't have any of the goo required to access fd etc. + */ +struct feature decstation_feature = { + 0,0,0,0,0,0,0,0,0,0,0,0,0, + maxine_rtc_read_data, + maxine_rtc_write_data +}; diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S --- v2.1.43/linux/arch/mips/dec/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/int-handler.S Thu Jun 26 12:33:36 1997 @@ -0,0 +1,260 @@ +/* + * arch/mips/dec/int-handler.S + * + * Copyright (C) 1995, 1996 Paul M. Antoine + * + * Written by Ralf Baechle and Andreas Busse, modified for DECStation + * support by Paul Antoine. + * + * NOTE: There are references to R4X00 code in here, because there is an + * upgrade module for Personal DECStations with such a CPU! + * + * FIXME: still plenty to do in this file, as much of the code hasn't been + * modified to suit the DECStation's interrupts. + */ +#include +#include +#include +#include +#include +#include +#include + + .text + .set noreorder +/* + * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x + * + * FIXME: this is *extremely* experimental, though it is probably o.k. for + * most DECStation models. + */ + NESTED(decstation_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 +/* + * FIXME: The following branch was: + * beqz t0,spurious_interrupt + * + * ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 ) + * to complain: + * + * "Can not represent relocation in this object file format"... + * + * hence this hack to branch foward a bit, and then jump + * Perhaps a later version of gas will cope? - Paul + */ + beqz t0,3f; + 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(decstation_handle_int) + +/* + * FIXME: The hack mentioned above. + */ +3: j spurious_interrupt + nop + +/* + * FIXME: the rest of this is pretty suspect, as it's straight from + * jazz.S... and I really haven't altered it at all - Paul + */ + +/* + * Used for keyboard driver's fake_keyboard_interrupt() + * (Paul, even for i386 this is no longer being used -- Ralf) + */ +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") + +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") + +/* + * Ethernet interrupt, remapped to level 15 + * NOTE: Due to a bug somewhere in the kernel I was not able + * to figure out, the PRINT() is necessary. Without this, + * I get a "gfp called nonatomically from interrupt 00000000". + * Only god knows why... Tell me if you find the reason! + * Andy, 6/16/95 + */ +loc_ethernet: PANIC("Unimplemented loc_ethernet\n") + +/* + * Keyboard interrupt, remapped to level 1 + */ +loc_keyboard: PANIC("Unimplemented loc_keyboard\n") + +loc_mouse: PANIC("Unimplemented loc_mouse handler") + +/* + * Serial port 1 IRQ, remapped to level 3 + */ +loc_serial1: PANIC("Unimplemented loc_serial handler") + +/* + * Serial port 2 IRQ, remapped to level 4 + */ +loc_serial2: PANIC("Unimplemented loc_serial handler") + +/* + * Parallel port IRQ, remapped to level 5 + */ +loc_parallel: PANIC("Unimplemented loc_parallel handler") + +/* + * Floppy IRQ, remapped to level 6 + */ +loc_floppy: PANIC("Unimplemented loc_floppy handler") + +/* + * Now call the real handler + */ +loc_call: la t0,IRQ_vectors # delay slot + + /* + * 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 */ + or t2,s1 +/* sh t2,JAZZ_IO_IRQ_ENABLE */ + + jr v0 + nop # delay slot + +ll_tc3: PANIC("Unimplemented tc3 interrupt handler") + +ll_fpu: PANIC("Unimplemented fpu interrupt handler") + +ll_io_error: PANIC("Unimplemented I/O write timeout interrupt handler") + +ll_rtc: PANIC("Unimplemented RTC interrupt handler") + +/* + * Timer IRQ + * We remap the timer irq to be more similar to a IBM compatible + */ +ll_timer: PANIC("Timer interrupt!\n"); +/* + * CPU count/compare IRQ (unused) + */ +ll_reset: li a0,0 + jal pmax_halt + li a1,0 # delay slot + +/* + * Now call the real handler + */ +call_real: la t0,IRQ_vectors # delay slot + + /* + * 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 + + jr v0 + nop # delay slot + +/* + * Just for debugging... load a0 with address of the point inside the + * framebuffer at which you want to draw a line of 16x32 pixels. + * Maxine's framebuffer starts at 0xaa000000. + */ + .set reorder + LEAF(drawline) + li t1,0xffffffff # set all pixels on + li t2,0x10 # we will write 16 words +1: sw t1,(a0) # write the first word + addiu a0,a0,4 # move our framebuffer pointer + addiu t2,t2,-1 # one less to do + bnez t2,1b # finished? + jr ra + END(drawline) + +/* + * FIXME: I have begun to alter this table to reflect Personal DECStation + * (i.e. Maxine) interrupts... Paul. + */ + .data + PTR ll_sw0 # SW0 + PTR ll_sw1 # SW1 + PTR ll_timer # Periodic interrupt + PTR ll_rtc # RTC periodic interrupt + PTR ll_io_error # Timeout on I/O writes + PTR ll_tc3 # TC slot 3, motherboard + PTR ll_reset # Halt keycode (CTRL+ALT+ENTER) +ll_vectors: PTR ll_fpu # FPU + +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 diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/ld.script linux/arch/mips/dec/ld.script --- v2.1.43/linux/arch/mips/dec/ld.script Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/ld.script Thu Jun 26 12:33:37 1997 @@ -0,0 +1,47 @@ +OUTPUT_FORMAT("ecoff-littlemips") +OUTPUT_ARCH(mips) +ENTRY(dec_entry) +SECTIONS +{ + /* This is probably a little simplistic, and is based on work by + * Chris Fraser of Softway Pty Ltd as used in his port of Vsta to + * the DECStation - Paul M. Antoine 21/1/96. + */ + . = 0x80030000; + .text : + { + *(.text) + . = ALIGN(0x10); + _etext = .; + __etext = .; + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + . = ALIGN(0x1000); + .data : + { + *(.data .rdata .rodata) + _edata = .; + __edata = .; + } + __bss_start = ALIGN(16) + 0x8000; + .sbss : + { + *(.sbss) + *(.scommon) + } + .bss : + { + *(.bss) + *(COMMON) + _end = ALIGN(4) ; + __end = ALIGN(4) ; + } + .reginfo : { + *(.reginfo) + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c --- v2.1.43/linux/arch/mips/dec/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/reset.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,28 @@ +/* + * linux/arch/mips/dec/process.c + * + * Reset a DECstation. + */ +#include +#include + +void dec_machine_restart(char *command) +{ + printk("Implement dec_machine_restart().\n"); + printk("Press reset to continue.\n"); + while(1); +} + +void dec_machine_halt(void) +{ + printk("Implement dec_machine_halt().\n"); + printk("Press reset to continue.\n"); + while(1); +} + +void dec_machine_power_off(void) +{ + printk("Implement dec_machine_power_off().\n"); + printk("Press reset to continue.\n"); + while(1); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.1.43/linux/arch/mips/dec/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/setup.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,50 @@ +/* + * Setup pointers to hardware dependand routines. + * + * 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) 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct feature decstation_feature; + +static void +dec_irq_setup(void) +{ + /* FIXME: should set up the clock as per above? */ + pmax_printf("Please write the IRQ setup code for the DECStation!\n"); +} + +void (*board_time_init)(struct irqaction *irq); + +static void dec_time_init(struct irqaction *irq) +{ + pmax_printf("Please write the time init code for the DECStation!\n"); +} + +extern void dec_machine_restart(char *command); +extern void dec_machine_halt(void); +extern void dec_machine_power_off(void). + +void +decstation_setup(void) +{ + irq_setup = dec_irq_setup; + board_time_init = dec_time_init; + /* FIXME: Setup fd_cacheflush */ + feature = &decstation_feature; /* FIXME: Will go away */ + + _machine_restart = dec_machine_restart; + _machine_halt = dec_machine_halt; + _machine_power_off = dec_machine_power_off; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.1.43/linux/arch/mips/defconfig Mon Apr 7 11:35:29 1997 +++ linux/arch/mips/defconfig Thu Jun 26 12:33:37 1997 @@ -3,42 +3,105 @@ # # -# Machine setup +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set + +# +# Machine selection # 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_SNI_RM200_PCI=y CONFIG_MIPS_JAZZ=y +CONFIG_PCI=y + +# +# CPU selection +# # CONFIG_CPU_R3000 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R4300 is not set CONFIG_CPU_R4X00=y -# CONFIG_CPU_R4600 is not set +# CONFIG_CPU_R5000 is not set # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set -CONFIG_TLB_SHUTDOWN=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -# CONFIG_ELF_KERNEL is not set + +# +# General setup +# +CONFIG_ELF_KERNEL=y CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_NET is not set -# CONFIG_SYSVIPC is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y CONFIG_SYSCTL=y +# CONFIG_PNP_PARPORT is not set # # Loadable module support # -# CONFIG_MODVERSIONS is not set +# CONFIG_MODULES is not set # -# block devices +# Floppy, IDE, and other block devices # CONFIG_BLK_DEV_FD=y -# CONFIG_ST506 is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_EZ is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Networking options +# +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_NET_ALIAS is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ACCT is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_PCTCP is not set +# CONFIG_INET_RARP is not set +CONFIG_PATH_MTU_DISCOVERY=y +CONFIG_IP_NOSR=y +# CONFIG_SKB_LARGE is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_AX25 is not set # # SCSI support @@ -46,6 +109,42 @@ # CONFIG_SCSI is not set # +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_MIPS_JAZZ_SONIC=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_EISA=y +CONFIG_PCNET32=y +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_DE4X5 is not set +# CONFIG_DEC_ELCP is not set +# CONFIG_DGRS is not set +# CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_DLCI is not set +# CONFIG_PPP is not set +# CONFIG_NET_RADIO is not set +# CONFIG_SLIP is not set +# CONFIG_TR is not set +# CONFIG_LAPBETHER is not set +# CONFIG_X25_ASY is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set @@ -53,30 +152,44 @@ # # Filesystems # +# CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y +# CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y -# CONFIG_ISO9660_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_RNFS_BOOTP=y +# CONFIG_RNFS_RARP is not set +CONFIG_NFSD=y +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set -# CONFIG_SMB_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_UFS_FS is not set # -# character devices +# Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# 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_SERIAL=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set +# CONFIG_FTAPE is not set # CONFIG_APM is not set -# CONFIG_SERIAL is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set # # Sound @@ -86,4 +199,5 @@ # # Kernel hacking # +# CONFIG_REMOTE_DEBUG is not set # CONFIG_PROFILE is not set diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/Makefile linux/arch/mips/deskstation/Makefile --- v2.1.43/linux/arch/mips/deskstation/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/Makefile Thu Jun 26 12:33:37 1997 @@ -0,0 +1,22 @@ +# +# Makefile for the Deskstation family specific parts of the 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: deskstation.o +O_TARGET := deskstation.o +O_OBJS := hw-access.o int-handler.o reset.o setup.o + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c --- v2.1.43/linux/arch/mips/deskstation/hw-access.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/hw-access.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,196 @@ +/* + * Low-level hardware access stuff for Deskstation rPC44/Tyne + * + * 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) 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int FLOPPY_IRQ; +extern int FLOPPY_DMA; + +asmlinkage extern void deskstation_handle_int(void); + +/* + * How to access the FDC's registers. + */ +static unsigned char +fd_inb(unsigned int port) +{ + return inb_p(port); +} + +static void +fd_outb(unsigned char value, unsigned int port) +{ + outb_p(value, port); +} + +/* + * How to access the floppy DMA functions. + */ +static void +fd_enable_dma(void) +{ + enable_dma(FLOPPY_DMA); +} + +static void +fd_disable_dma(void) +{ + disable_dma(FLOPPY_DMA); +} + +static int +fd_request_dma(void) +{ + return request_dma(FLOPPY_DMA, "floppy"); +} + +static void +fd_free_dma(void) +{ + free_dma(FLOPPY_DMA); +} + +static void +fd_clear_dma_ff(void) +{ + clear_dma_ff(FLOPPY_DMA); +} + +static void +fd_set_dma_mode(char mode) +{ + set_dma_mode(FLOPPY_DMA, mode); +} + +static void +fd_set_dma_addr(unsigned int addr) +{ + set_dma_addr(FLOPPY_DMA, addr); +} + +static void +fd_set_dma_count(unsigned int count) +{ + set_dma_count(FLOPPY_DMA, count); +} + +static int +fd_get_dma_residue(void) +{ + return get_dma_residue(FLOPPY_DMA); +} + +static void +fd_enable_irq(void) +{ + enable_irq(FLOPPY_IRQ); +} + +static void +fd_disable_irq(void) +{ + disable_irq(FLOPPY_IRQ); +} + +void +deskstation_fd_cacheflush(const void *addr, size_t size) +{ + flush_cache_all(); +} + +/* + * RTC stuff + */ +static unsigned char * +rtc_read_data() +{ + return 0; +} + +static void +rtc_write_data(unsigned char data) +{ +} + +/* + * KLUDGE + */ +static unsigned long +vdma_alloc(unsigned long paddr, unsigned long size) +{ + return 0; +} + +#ifdef CONFIG_DESKSTATION_TYNE +struct feature deskstation_tyne_feature = { + /* + * How to access the floppy controller's ports + */ + fd_inb, + fd_outb, + /* + * How to access the floppy DMA functions. + */ + fd_enable_dma, + fd_disable_dma, + fd_request_dma, + fd_free_dma, + fd_clear_dma_ff, + fd_set_dma_mode, + fd_set_dma_addr, + fd_set_dma_count, + fd_get_dma_residue, + fd_enable_irq, + fd_disable_irq, + /* + * How to access the RTC functions. + */ + rtc_read_data, + rtc_write_data +}; +#endif + +#ifdef CONFIG_DESKSTATION_RPC44 +struct feature deskstation_rpc44_feature = { + /* + * How to access the floppy controller's ports + */ + fd_inb, + fd_outb, + /* + * How to access the floppy DMA functions. + */ + fd_enable_dma, + fd_disable_dma, + fd_request_dma, + fd_free_dma, + fd_clear_dma_ff, + fd_set_dma_mode, + fd_set_dma_addr, + fd_set_dma_count, + fd_get_dma_residue, + fd_enable_irq, + fd_disable_irq, + /* + * How to access the RTC functions. + */ + rtc_read_data, + rtc_write_data +}; +#endif diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/int-handler.S linux/arch/mips/deskstation/int-handler.S --- v2.1.43/linux/arch/mips/deskstation/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/int-handler.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,111 @@ +/* + * Deskstation rPC44/Tyne specific interrupt handler code + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include + +#error "FIXME - PORT_BASE is defined to port_base which breaks this file" + + .text + .set noreorder + .set noat + .align 5 + NESTED(deskstation_handle_int, PT_SIZE, sp) + SAVE_ALL + REG_S sp,PT_OR2(sp) + CLI + .set at + lui s0,%hi(PORT_BASE) + li a0,0x0f + sb a0,%lo(PORT_BASE+0x20)(s0) # poll command + lb a0,%lo(PORT_BASE+0x20)(s0) # read result + bgtz a0,poll_second + andi a0,7 + beq a0,2,poll_second # cascade? + li s1,1 # delay slot + /* + * Acknowledge first pic + */ + lb t2,%lo(PORT_BASE+0x21)(s0) + lui s4,%hi(cache_21) + lb t0,%lo(cache_21)(s4) + sllv s1,s1,a0 + or t0,s1 + sb t0,%lo(cache_21)(s4) + sb t0,%lo(PORT_BASE+0x21)(s0) + li t2,0x20 + sb t2,%lo(PORT_BASE+0x20)(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + /* + * Unblock first pic + */ + lbu t1,%lo(PORT_BASE+0x21)(s0) + lb t1,%lo(cache_21)(s4) + nor s1,zero,s1 + and t1,s1 + sb t1,%lo(cache_21)(s4) + jr v0 + sb t1,%lo(PORT_BASE+0x21)(s0) # delay slot + + /* + * Cascade interrupt from second PIC + */ + .align 5 +poll_second: li a0,0x0f + sb a0,%lo(PORT_BASE+0xa0)(s0) # poll command + lb a0,%lo(PORT_BASE+0xa0)(s0) # read result + bgtz a0,3f + andi a0,7 + /* + * Acknowledge second pic + */ + lbu t2,%lo(PORT_BASE+0xa1)(s0) + lui s4,%hi(cache_A1) + lb t3,%lo(cache_A1)(s4) + sllv s1,s1,a0 + or 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) + sb t3,%lo(PORT_BASE+0x20)(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + addiu a0,8 + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + /* + * Unblock second pic + */ + lb t1,%lo(PORT_BASE+0xa1)(s0) + lb t1,%lo(cache_A1)(s4) + 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 + +/* + * "Jump extender" to reach spurious_interrupt + */ +3: j spurious_interrupt + nop # delay slot + END(deskstation_handle_int) diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/io.c linux/arch/mips/deskstation/io.c --- v2.1.43/linux/arch/mips/deskstation/io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/io.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,68 @@ +/* + * 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. + * + * Low level I/O functions for Jazz family machine. + * + * FIXME: This implementation fits the Tyne. How does the EISA rPC44 handle + * the eight high address bits? + */ +#include +#include +#include +#include + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped + * for the processor. + */ +extern unsigned long isa_slot_offset; + +static unsigned char deskstation_readb(unsigned long addr) +{ + return *(volatile unsigned char *) (isa_slot_offset + addr); +} + +static unsigned short deskstation_readw(unsigned long addr) +{ + return *(volatile unsigned short *) (isa_slot_offset + addr); +} + +static unsigned int deskstation_readl(unsigned long addr) +{ + return *(volatile unsigned int *) (isa_slot_offset + addr); +} + +static void deskstation_writeb(unsigned char val, unsigned long addr) +{ + *(volatile unsigned char *) (isa_slot_offset + addr) = val; +} + +static void deskstation_writew(unsigned short val, unsigned long addr) +{ + *(volatile unsigned char *) (isa_slot_offset + addr) = val; +} + +static void deskstation_writel(unsigned int val, unsigned long addr) +{ + *(volatile unsigned char *) (isa_slot_offset + addr) = val; +} + +static void deskstation_memset_io(unsigned long addr, int val, unsigned long len) +{ + addr += isa_slot_offset; + memset((void *)addr, val, len); +} + +static void deskstation_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) +{ + from += isa_slot_offset; + memcpy((void *)to, (void *)from, len); +} + +static void deskstation_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) +{ + to += isa_slot_offset; + memcpy((void *)to, (void *)from, len); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/reset.c linux/arch/mips/deskstation/reset.c --- v2.1.43/linux/arch/mips/deskstation/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/reset.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,29 @@ +/* + * linux/arch/mips/deskstation/process.c + * + * Reset a Deskstation. + */ +#include +#include +#include + +void deskstation_machine_restart(void) +{ + printk("Implement deskstation_machine_restart().\n"); + printk("Press reset to continue.\n"); + while(1); +} + +void deskstation_machine_halt(void) +{ + printk("Implement deskstation_machine_halt().\n"); + printk("Press reset to continue.\n"); + while(1); +} + +void deskstation_machine_power_off(void) +{ + printk("Implement dec_machine_power_off().\n"); + printk("Press reset to continue.\n"); + while(1); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c --- v2.1.43/linux/arch/mips/deskstation/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/deskstation/setup.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,110 @@ +/* + * Setup pointers to hardware dependand routines. + * + * 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) 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Initial irq handlers. + */ +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; + +extern asmlinkage void deskstation_handle_int(void); +extern asmlinkage void deskstation_fd_cacheflush(const void *addr, size_t size); +extern struct feature deskstation_tyne_feature; +extern struct feature deskstation_rpc44_feature; + +extern void deskstation_machine_reboot(void); +extern void deskstation_machine_halt(void); +extern void deskstation_machine_power_off(void); + +#ifdef CONFIG_DESKSTATION_TYNE +unsigned long mips_dma_cache_size = 0; +unsigned long mips_dma_cache_base = KSEG0; + +__initfunc(static void tyne_irq_setup(void)) +{ + set_except_vector(0, deskstation_handle_int); + /* 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 */ + request_region(0x20,0x20, "pic1"); + request_region(0xa0,0x20, "pic2"); + setup_x86_irq(2, &irq2); +} +#endif + +#ifdef CONFIG_DESKSTATION_RPC44 +__initfunc(static void rpc44_irq_setup(void)) +{ + /* + * For the moment just steal the TYNE support. In the + * future, we need to consider merging the two -- imp + */ + set_except_vector(0, deskstation_handle_int); + /* 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 */ + request_region(0x20,0x20, "pic1"); + request_region(0xa0,0x20, "pic2"); + setup_x86_irq(2, &irq2); + set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); +} +#endif + +__initfunc(void deskstation_setup(void)) +{ + switch(mips_machtype) { +#ifdef CONFIG_DESKSTATION_TYNE + case MACH_DESKSTATION_TYNE: + atag = bi_TagFind(tag_dma_cache_size); + memcpy(&mips_dma_cache_size, TAGVALPTR(atag), atag->size); + + atag = bi_TagFind(tag_dma_cache_base); + memcpy(&mips_dma_cache_base, TAGVALPTR(atag), atag->size); + + irq_setup = tyne_irq_setup; + feature = &deskstation_tyne_feature; + isa_slot_offset = 0xe3000000; // Will go away + break; +#endif +#ifdef CONFIG_DESKSTATION_RPC44 + case MACH_DESKSTATION_RPC44: + irq_setup = rpc44_irq_setup; + mips_memory_upper = KSEG0 + (32 << 20); /* xxx fixme imp */ + feature = &deskstation_rpc44_feature; // Will go away + isa_slot_offset = 0xa0000000; + break; +#endif + } + fd_cacheflush = deskstation_fd_cacheflush; + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x70,0x10,"rtc"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile --- v2.1.43/linux/arch/mips/jazz/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/Makefile Thu Jun 26 12:33:37 1997 @@ -0,0 +1,26 @@ +# +# Makefile for the Jazz family specific parts of the 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: jazz.o +O_TARGET := jazz.o +O_OBJS := hw-access.o int-handler.o jazzdma.o reset.o setup.o + +ifdef CONFIG_VIDEO_G364 +O_OBJS += g364.o +endif + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c --- v2.1.43/linux/arch/mips/jazz/g364.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/g364.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,419 @@ +/* + * linux/drivers/char/g364.c + * + * Copyright (C) 1996 Wayne Hodgen + * + * Based on and using chunks of Jay Estabrooks tga.c + * + * This module exports the console io support for Inmos's G364 controller + * used in Mips Magnums and clones. Based on the hardware desc for the + * Olivetti M700-10 ie. an Inmos G364 based card in a dedicated video slot, + * 2MB dual ported VRAM with a 64 bit data path, 256 color lookup table, + * palette of 16.7M and a user definable 64x64 hardware cursor. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../../../drivers/char/kbd_kern.h" +#include "../../../drivers/char/vt_kern.h" +#include "../../../drivers/char/consolemap.h" +#include "../../../drivers/char/selection.h" +#include "../../../drivers/char/console_struct.h" + +extern void register_console(void (*proc)(const char *)); +extern void console_print(const char *); +unsigned video_res_x; + +/* + * Various defines for the G364 + */ +#define G364_MEM_BASE 0xe0800000 +#define G364_PORT_BASE 0xe0200000 +#define ID_REG 0xe0200000 /* Read only */ +#define BOOT_REG 0xe0280000 +#define TIMING_REG 0xe0280108 /* to 0x080170 - DON'T TOUCH! */ +#define MASK_REG 0xe0280200 +#define CTLA_REG 0xe0280300 +#define CURS_TOGGLE 0x800000 +#define BIT_PER_PIX 0x700000 /* bits 22 to 20 of Control A */ +#define DELAY_SAMPLE 0x080000 +#define PORT_INTER 0x040000 +#define PIX_PIPE_DEL 0x030000 /* bits 17 and 16 of Control A */ +#define PIX_PIPE_DEL2 0x008000 /* same as above - don't ask me why */ +#define TR_CYCLE_TOG 0x004000 +#define VRAM_ADR_INC 0x003000 /* bits 13 and 12 of Control A */ +#define BLANK_OFF 0x000800 +#define FORCE_BLANK 0x000400 +#define BLK_FUN_SWTCH 0x000200 +#define BLANK_IO 0x000100 +#define BLANK_LEVEL 0x000080 +#define A_VID_FORM 0x000040 +#define D_SYNC_FORM 0x000020 +#define FRAME_FLY_PAT 0x000010 +#define OP_MODE 0x000008 +#define INTL_STAND 0x000004 +#define SCRN_FORM 0x000002 +#define ENABLE_VTG 0x000001 +#define TOP_REG 0xe0280400 +#define CURS_PAL_REG 0xe0280508 /* to 0x080518 */ +#define CHKSUM_REG 0xe0280600 /* to 0x080610 - unused */ +#define CURS_POS_REG 0xe0280638 +#define CLR_PAL_REG 0xe0280800 /* to 0x080ff8 */ +#define CURS_PAT_REG 0xe0281000 /* to 0x081ff8 */ +#define MON_ID_REG 0xe0300000 /* unused */ +#define RESET_REG 0xe0380000 /* Write only */ + +/* + * built-in font management constants + * + * NOTE: the built-in font is 8x16, and the video resolution + * is either 1280x1024 @ 60Hz or 1024x768 @ 60 or 78Hz. + */ +#define FONTSIZE_X 8 /* 8 pixels wide */ +#define FONTSIZE_Y 16 /* 16 pixels high */ + +unsigned char g364_font[] = { +#include "g364.fnt" +}; + +u32 g364_cursor[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0xffff0000,0,0,0,0xffff0000,0,0,0,0xffff0000,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +#ifdef CONFIG_REMOTE_DEBUG +/* #define DEBUG_G364 */ + +extern int putDebugChar(char c); + +void +putDebugString(char *d_str) +{ + while (*d_str != '\0') { + putDebugChar(*d_str); + d_str++; + } + if (*--d_str != '\n') + putDebugChar('\n'); +} +#endif + +void g364_clear_screen(void); + +int cursor_initialised=0; + +unsigned long +con_type_init(unsigned long kmem_start, const char **display_desc) +{ + can_do_color = 1; + + /* + * fake the screen memory with some CPU memory + */ + video_mem_base = kmem_start; + kmem_start += video_screen_size; + video_mem_term = kmem_start; + video_type = VIDEO_TYPE_MIPS_G364; + video_res_x = video_num_columns * FONTSIZE_X; + + *display_desc = "G364"; + + return kmem_start; +} + +con_type_init_finish(void) +{ +} + +void +__set_origin(unsigned short offset) +{ + /* + * should not be called, but if so, do nothing... + */ +} + +/* + * Hide the cursor from view, during blanking, usually... + */ +void +hide_cursor(void) +{ +/* *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE; */ +} + +void +init_g364_cursor(void) +{ + volatile unsigned int *ptr = (unsigned int *) CURS_PAL_REG; + + *ptr |= 0x00ffffff; + ptr[2] |= 0x00ffffff; + ptr[4] |= 0x00ffffff; + + memcpy((unsigned int *)CURS_PAT_REG, &g364_cursor, 1024); + cursor_initialised = 1; +} + +/* + * Set the cursor on. + */ +void +set_cursor(int currcons) +{ +/* + if (!cursor_initialised) + init_g364_cursor(); + + if (console_blanked) + return; + + *(unsigned int *) CTLA_REG |= CURS_TOGGLE; +*/ +} + +/* + * NOTE: get_scrmem() and set_scrmem() are here only because + * the VGA version of set_scrmem() has some direct VGA references. + */ +void +get_scrmem(int currcons) +{ + memcpyw((unsigned short *)vc_scrbuf[currcons], + (unsigned short *)origin, video_screen_size); + origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; + scr_end = video_mem_end = video_mem_start + video_screen_size; + pos = origin + y*video_size_row + (x<<1); +} + +void +set_scrmem(int currcons, long offset) +{ + if (video_mem_term - video_mem_base < offset + video_screen_size) + offset = 0; /* strange ... */ + memcpyw((unsigned short *)(video_mem_base + offset), + (unsigned short *) origin, video_screen_size); + video_mem_start = video_mem_base; + video_mem_end = video_mem_term; + origin = video_mem_base + offset; + scr_end = origin + video_screen_size; + pos = origin + y*video_size_row + (x<<1); +} + +/* + * Fill out later + */ +void +set_palette(void) +{ + int i, j; + volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG; + + for (i = 0; i < 16; i++,ptr+=2) { + j = color_table[i]; + *ptr = ((default_red[j] << 16) | + (default_grn[j] << 8) | + (default_blu[j])); + } +} + +/* + * NOTE: + * this is here, and not in console.c, because the VGA version + * tests the controller type to see if color can be done. We *KNOW* + * that we can do color on the G364. + * + */ + +int +set_get_cmap(unsigned char * arg, int set) +{ + int i; + + for (i=0; i<16; i++) { + if (set) { + if (!access_ok(VERIFY_READ, (void *)arg, 16*3)) goto fault; + if (__get_user(default_red[i], arg++)) goto fault; + if (__get_user(default_grn[i], arg++)) goto fault; + if (__get_user(default_blu[i], arg++)) goto fault; + } else { + if (!access_ok(VERIFY_WRITE, (void *)arg, 16*3)) goto fault; + if (__put_user(default_red[i], arg++)) goto fault; + if (__put_user(default_grn[i], arg++)) goto fault; + if (__put_user(default_blu[i], arg++)) goto fault; + } + } + if (set) { + for (i=0; ivc_palette[k++] = default_red[j]; + vc_cons[i].d->vc_palette[k++] = default_grn[j]; + vc_cons[i].d->vc_palette[k++] = default_blu[j]; + } + } + set_palette() ; + } + + return 0; + +fault: + return -EFAULT; +} + +/* + * Adjust the screen to fit a font of a certain height + * + * Returns < 0 for error, 0 if nothing changed, and the number + * of lines on the adjusted console if changed. + * + * for now, we only support the built-in font... + */ +int +con_adjust_height(unsigned long fontheight) +{ + return -EINVAL; +} + +/* + * PIO_FONT support. + * + * for now, we will use/allow *only* our built-in font... + */ +int +set_get_font(char * arg, int set, int ch512) +{ + return -EINVAL; +} + +/* + * print a character to a graphics console. + */ +void +g364_blitc(unsigned short charattr, unsigned long addr) +{ + int row, col, temp; + register unsigned long long *dst, *font_row; + register int i; + char c; + + /* + * calculate (row,col) from addr and video_mem_base + */ + temp = (addr - video_mem_base) >> 1; + col = temp % 128; + row = (temp - col) / 128; + + /* + * calculate destination address + */ + dst = (unsigned long long *) ( G364_MEM_BASE + + ( row * video_res_x * FONTSIZE_Y ) + + ( col * FONTSIZE_X ) ); + + c = charattr & 0x00ff; + if (c == 0x20) { + for (i=0; i < FONTSIZE_Y; i++, dst += video_num_columns) + *dst = 0x00000000; + } else { + font_row = (unsigned long long *) &g364_font[(c << 7)]; + for (i=0; i < FONTSIZE_Y; i++, font_row++, dst += video_num_columns) + *dst = *font_row; + } +} + +/* + * print a character to a graphics console. Colour version, slower! + */ +void +g364_blitc_colour(unsigned short charattr, unsigned long addr) +{ + int row, col, temp, c, attrib; + register unsigned int fgmask, bgmask; + register unsigned long long *dst, *font_row; + register int i, stride; + + c = charattr & 0x00ff; + attrib = (charattr >> 8) & 0x00ff; + + /* + * extract foreground and background indices + * NOTE: we always treat blink/underline bits as color for now... + */ + fgmask = attrib & 0x0f; + bgmask = (attrib >> 4) & 0x0f; + + /* i = (c & 0xff) << 7; NOTE: assumption of 128 bytes per character bitmap */ + + /* + * calculate (row,col) from addr and video_mem_base + */ + temp = (addr - video_mem_base) >> 1; + col = temp % 128; + row = (temp - col) / 128; + stride = video_res_x / 8; + + /* + * calculate destination address + */ + dst = (unsigned long long *) ( G364_MEM_BASE + + ( row * video_res_x * FONTSIZE_Y ) + + ( col * FONTSIZE_X ) ); + + font_row = (unsigned long long *) &g364_font[((c & 0xff) << 7)]; + + for (i=0; i < FONTSIZE_Y; i++, font_row++, dst += stride) { + *dst = *font_row; + } +} + +/* + * dummy routines for the VESA blanking code, which is VGA only, + * so we don't have to carry that stuff around for the G364... + */ +void +vesa_powerdown(void) +{ +} + +void +vesa_blank(void) +{ +} + +void +vesa_unblank(void) +{ +} + +void +set_vesa_blanking(const unsigned long arg) +{ +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/g364.fnt linux/arch/mips/jazz/g364.fnt --- v2.1.43/linux/arch/mips/jazz/g364.fnt Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/g364.fnt Thu Jun 26 12:33:37 1997 @@ -0,0 +1,4097 @@ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x00,0x07,0x07,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x07, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x07, +0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x07, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07, +0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07, +0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07, +0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07, +0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07, +0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07, +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x07,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x07, +0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07, +0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x07, +0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x07, +0x00,0x07,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x07,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07, +0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07, +0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x07, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00, +0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00, +0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00, +0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00, +0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00, +0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0 diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c --- v2.1.43/linux/arch/mips/jazz/hw-access.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/hw-access.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,148 @@ +/* + * Low-level hardware access stuff for Jazz family machines. + * + * 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, 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned char +fd_inb(unsigned int port) +{ + unsigned char c; + + c = *(volatile unsigned char *) port; + udelay(1); + + return c; +} + +static void +fd_outb(unsigned char value, unsigned int port) +{ + *(volatile unsigned char *) port = value; +} + +/* + * How to access the floppy DMA functions. + */ +static void +fd_enable_dma(void) +{ + vdma_enable(JAZZ_FLOPPY_DMA); +} + +static void +fd_disable_dma(void) +{ + vdma_disable(JAZZ_FLOPPY_DMA); +} + +static int +fd_request_dma(void) +{ + return 0; +} + +static void +fd_free_dma(void) +{ +} + +static void +fd_clear_dma_ff(void) +{ +} + +static void +fd_set_dma_mode(char mode) +{ + vdma_set_mode(JAZZ_FLOPPY_DMA, mode); +} + +static void +fd_set_dma_addr(unsigned int a) +{ + vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a))); +} + +static void +fd_set_dma_count(unsigned int count) +{ + vdma_set_count(JAZZ_FLOPPY_DMA, count); +} + +static int +fd_get_dma_residue(void) +{ + return vdma_get_residue(JAZZ_FLOPPY_DMA); +} + +static void +fd_enable_irq(void) +{ +} + +static void +fd_disable_irq(void) +{ +} + +void +jazz_fd_cacheflush(const void *addr, size_t size) +{ + flush_cache_all(); +} + +static unsigned char +rtc_read_data(unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + return *(char *)JAZZ_RTC_BASE; +} + +static void +rtc_write_data(unsigned char data, unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + *(char *)JAZZ_RTC_BASE = data; +} + +struct feature jazz_feature = { + /* + * How to access the floppy controller's ports + */ + fd_inb, + fd_outb, + /* + * How to access the floppy DMA functions. + */ + fd_enable_dma, + fd_disable_dma, + fd_request_dma, + fd_free_dma, + fd_clear_dma_ff, + fd_set_dma_mode, + fd_set_dma_addr, + fd_set_dma_count, + fd_get_dma_residue, + fd_enable_irq, + fd_disable_irq, + /* + * How to access the RTC functions. + */ + rtc_read_data, + rtc_write_data +}; diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S --- v2.1.43/linux/arch/mips/jazz/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/int-handler.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,356 @@ +/* + * arch/mips/jazz/pica.S + * + * Copyright (C) 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Jazz family specific stuff + * + * To do: On Jazz machines we remap some non-ISA interrupts to ISA + * interrupts. These interrupts should use their own vectors. + * Squeeze the last cycles out of the handlers. Only a dead + * cycle is a good cycle. + */ +#include +#include +#include +#include +#include +#include + +/* + * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards + */ + .set noreorder + + NESTED(jazz_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + REG_S sp,PT_OR2(sp) + 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,3f + 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(jazz_handle_int) + +ll_sw0: li s1,~IE_SW0 + mfc0 t0,CP0_CAUSE + and t0,s1 + mtc0 t0,CP0_CAUSE + PANIC("Unimplemented sw0 handler") + +ll_sw1: li s1,~IE_SW1 + mfc0 t0,CP0_CAUSE + and t0,s1 + mtc0 t0,CP0_CAUSE + 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 PTRSIZE == 8 /* True 64 bit kernel */ + dsll t0,1 +#endif + .set reorder + LONG_L t0,local_vector(t0) + jr t0 + .set noreorder + +/* + * The braindead PICA hardware gives us no way to distinguish if we really + * received interrupt 7 from the (E)ISA bus or if we just received an + * interrupt with no findable cause. This sometimes happens with braindead + * cards. Oh well - for all the Jazz boxes slots are more or less just + * whistles and bells and we're aware of the problem. + */ +ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK + lui s0,%hi(JAZZ_PORT_BASE) + li s1,1 + andi t0,a0,8 # which pic? + bnez t0,ack_second + andi a0,7 # delay slot + + /* + * Acknowledge first pic + */ + lb t2,%lo(JAZZ_PORT_BASE)+0x21(s0) + lui s4,%hi(cache_21) + lb t0,%lo(cache_21)(s4) + sllv s1,s1,a0 + or t0,s1 + sb t0,%lo(cache_21)(s4) + sb t0,%lo(JAZZ_PORT_BASE)+0x21(s0) + li t2,0x20 + sb t2,%lo(JAZZ_PORT_BASE)+0x20(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + /* + * Unblock first pic + */ + lbu a0,%lo(JAZZ_PORT_BASE)+0x21(s0) + lb a0,%lo(cache_21)(s4) + nor s1,zero,s1 + and a0,s1 + sb a0,%lo(cache_21)(s4) + jr v0 + sb a0,%lo(JAZZ_PORT_BASE)+0x21(s0) # delay slot + + .align 5 +ack_second: /* + * Acknowledge second pic + */ + lbu t2,%lo(JAZZ_PORT_BASE)+0xa1(s0) + lui s4,%hi(cache_A1) + lb t3,%lo(cache_A1)(s4) + sllv s1,s1,a0 + or t3,s1 + sb t3,%lo(cache_A1)(s4) + sb t3,%lo(JAZZ_PORT_BASE)+0xa1(s0) + li t3,0x20 + sb t3,%lo(JAZZ_PORT_BASE)+0xa0(s0) + sb t3,%lo(JAZZ_PORT_BASE)+0x20(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + addiu a0,8 + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + + /* + * Unblock second pic + */ + lb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0) + lb a0,%lo(cache_A1)(s4) + nor s1,zero,s1 + and a0,s1 + sb a0,%lo(cache_A1)(s4) + jr v0 + sb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0) # delay slot + +/* + * Hmm... This is not just a plain PC clone so the question is + * which devices on Jazz machines can generate an (E)ISA NMI? + * (Writing to nonexistant memory?) + */ +ll_isa_nmi: li s1,~IE_IRQ3 + PANIC("Unimplemented isa_nmi handler") + +/* + * Timer IRQ - remapped to be more similar to an IBM compatible. + * + * The timer interrupt is handled specially to insure that the jiffies + * variable is updated at all times. Specifically, the timer interrupt is + * just like the complete handlers except that it is invoked with interrupts + * disabled and should never re-enable them. If other interrupts were + * allowed to be processed while the timer interrupt is active, then the + * other interrupts would have to avoid using the jiffies variable for delay + * and interval timing operations to avoid hanging the system. + */ +ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read + li s1,~IE_IRQ4 + + li a0,0 + jal do_IRQ + move a1,sp # delay slot + + mfc0 t0,CP0_STATUS # disable interrupts again + ori t0,1 + xori t0,1 + mtc0 t0,CP0_STATUS + + j ret_from_sys_call + nop # delay slot + +/* + * CPU count/compare IRQ (unused) + */ +ll_count: j return + mtc0 zero,CP0_COMPARE + +#if 0 +/* + * Call the handler for the interrupt + * (Currently unused) + */ +call_real: la t0,IRQ_vectors + + /* + * 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 + + jr v0 + nop # delay slot +#endif + + .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 + + /* + * Interrupt handlers for local devices. + */ + .text +loc_no_irq: PANIC("Unimplemented loc_no_irq handler") +/* + * Parallel port IRQ, remapped to level 5 + */ +loc_parallel: li s1,~JAZZ_IE_PARALLEL + li a0,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 a0,JAZZ_FLOPPY_IRQ + b loc_call + li t3,PTRSIZE*JAZZ_FLOPPY_IRQ # delay slot + +/* + * 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 13 + */ +loc_ethernet: li s1,~JAZZ_IE_ETHERNET + li a0,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 a0,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 a0,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 a0,JAZZ_SERIAL2_IRQ + b loc_call + li t3,PTRSIZE*JAZZ_SERIAL2_IRQ # delay slot + +/* + * Call the interrupt handler for an interrupt generated by a + * local device. + */ +loc_call: la t0,IRQ_vectors # delay slot + + /* + * 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 + or t2,s1 + sh t2,JAZZ_IO_IRQ_ENABLE + + jr v0 + nop # delay slot + +/* + * "Jump extender" to reach spurious_interrupt + */ +3: j spurious_interrupt + nop # delay slot + +/* + * Vectors for interrupts generated by local devices + */ + .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 diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/io.c linux/arch/mips/jazz/io.c --- v2.1.43/linux/arch/mips/jazz/io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/io.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,136 @@ +/* + * 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. + * + * Low level I/O functions for Jazz family machines. + * + * Copyright (C) 1997 by Ralf Baechle. + */ +#include +#include +#include +#include +#include +#include + +/* + * Map an 16mb segment of the EISA address space to 0xe3000000; + */ +static inline void map_eisa_address(unsigned long address) +{ + /* XXX */ + /* We've got an wired entry in the TLB. We just need to modify it. + fast and clean. But since we want to get rid of wired entries + things are a little bit more complicated ... */ +} + +static unsigned char jazz_readb(unsigned long addr) +{ + unsigned char res; + + map_eisa_address(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr); + + return res; +} + +static unsigned short jazz_readw(unsigned long addr) +{ + unsigned short res; + + map_eisa_address(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr); + + return res; +} + +static unsigned int jazz_readl(unsigned long addr) +{ + unsigned int res; + + map_eisa_address(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr); + + return res; +} + +static void jazz_writeb(unsigned char val, unsigned long addr) +{ + map_eisa_address(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val; +} + +static void jazz_writew(unsigned short val, unsigned long addr) +{ + map_eisa_address(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val; +} + +static void jazz_writel(unsigned int val, unsigned long addr) +{ + map_eisa_address(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val; +} + +static void jazz_memset_io(unsigned long addr, int val, unsigned long len) +{ + unsigned long waddr; + + waddr = JAZZ_EISA_BASE | (addr & 0xffffff); + while(len) { + unsigned long fraglen; + + fraglen = (~addr + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + map_eisa_address(addr); + memset((char *)waddr, val, fraglen); + addr += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } +} + +static void jazz_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) +{ + unsigned long waddr; + + waddr = JAZZ_EISA_BASE | (from & 0xffffff); + while(len) { + unsigned long fraglen; + + fraglen = (~from + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + map_eisa_address(from); + memcpy((void *)to, (void *)waddr, fraglen); + to += fraglen; + from += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } +} + +static void jazz_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) +{ + unsigned long waddr; + + waddr = JAZZ_EISA_BASE | (to & 0xffffff); + while(len) { + unsigned long fraglen; + + fraglen = (~to + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + map_eisa_address(to); + memcpy((char *)to + JAZZ_EISA_BASE, (void *)from, fraglen); + to += fraglen; + from += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.1.43/linux/arch/mips/jazz/jazzdma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/jazzdma.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,515 @@ +/* + * arch/mips/jazz/jazzdma.c + * + * Mips Jazz DMA controller support + * Copyright (C) 1995, 1996 by Andreas Busse + * + * NOTE: Some of the argument checking 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 +#include +#include + +/* + * Set this to one to enable additional vdma debug code. + */ +#define CONF_DEBUG_VDMA 0 + +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; + +/* + * 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 inline 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 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, pages, npages; + + 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 */ + } + + npages = 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)); +} + +/* + * Print DMA statistics + */ +void vdma_stats(void) +{ + int i; + + printk("vdma_stats: CONFIG: %08x\n", + r4030_read_reg32(JAZZ_R4030_CONFIG)); + printk("R4030 translation table base: %08x\n", + r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE)); + printk("R4030 translation table limit: %08x\n", + r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM)); + printk("vdma_stats: INV_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_INV_ADDR)); + printk("vdma_stats: R_FAIL_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR)); + printk("vdma_stats: M_FAIL_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR)); + printk("vdma_stats: IRQ_SOURCE: %08x\n", + r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE)); + printk("vdma_stats: I386_ERROR: %08x\n", + r4030_read_reg32(JAZZ_R4030_I386_ERROR)); + printk("vdma_chnl_modes: "); + for (i=0; i<8; i++) + printk("%04x ", + (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5))); + printk("\n"); + printk("vdma_chnl_enables: "); + for (i=0; i<8; i++) + printk("%04x ", + (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5))); + printk("\n"); +} + +/* + * DMA transfer functions + */ + +/* + * Enable a DMA channel. Also clear any error conditions. + */ +void vdma_enable(int channel) +{ + int status; + + if (vdma_debug) + printk("vdma_enable: channel %d\n",channel); + + /* + * Check error conditions first + */ + status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); + if (status & 0x400) + printk("VDMA: Channel %d: Address error!\n",channel); + if (status & 0x200) + printk("VDMA: Channel %d: Memory error!\n",channel); + + /* + * Clear all interrupt flags + */ + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), + R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR); + + /* + * Enable the desired channel + */ + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) | + R4030_CHNL_ENABLE); +} + +/* + * Disable a DMA channel + */ +void vdma_disable(int channel) +{ + if (vdma_debug) + { + int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); + + printk("vdma_disable: channel %d\n",channel); + printk("VDMA: channel %d status: %04x (%s) mode: " + "%02x addr: %06x count: %06x\n", + channel,status,((status & 0x600) ? "ERROR" : "OK"), + (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)), + (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)), + (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5))); + } + + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) & + ~R4030_CHNL_ENABLE); + + /* + * After disabling a DMA channel a remote bus register should be + * read to ensure that the current DMA acknowledge cycle is completed. + */ + *((volatile unsigned int *)JAZZ_DUMMY_DEVICE); +} + +/* + * Set DMA mode. This function accepts the mode values used + * to set a PC-style DMA controller. For the SCSI and FDC + * channels, we also set the default modes each time we're + * called. + * NOTE: The FAST and BURST dma modes are supported by the + * R4030 Rev. 2 and PICA chipsets only. I leave them disabled + * for now. + */ +void vdma_set_mode(int channel, int mode) +{ + if (vdma_debug) + printk("vdma_set_mode: channel %d, mode 0x%x\n", channel, mode); + + switch(channel) + { + case JAZZ_SCSI_DMA: /* scsi */ + r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5), +/* R4030_MODE_FAST | */ +/* R4030_MODE_BURST | */ + R4030_MODE_INTR_EN | + R4030_MODE_WIDTH_16 | + R4030_MODE_ATIME_80); + break; + + case JAZZ_FLOPPY_DMA: /* floppy */ + r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5), +/* R4030_MODE_FAST | */ +/* R4030_MODE_BURST | */ + R4030_MODE_INTR_EN | + R4030_MODE_WIDTH_8 | + R4030_MODE_ATIME_120); + break; + + case JAZZ_AUDIOL_DMA: + case JAZZ_AUDIOR_DMA: + printk("VDMA: Audio DMA not supported yet.\n"); + break; + + default: + printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n", + channel); + } + + switch(mode) + { + case DMA_MODE_READ: + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) & + ~R4030_CHNL_WRITE); + break; + + case DMA_MODE_WRITE: + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) | + R4030_CHNL_WRITE); + break; + + default: + printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode); + } +} + +/* + * Set Transfer Address + */ +void vdma_set_addr(int channel, long addr) +{ + if (vdma_debug) + printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr); + + r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr); +} + +/* + * Set Transfer Count + */ +void vdma_set_count(int channel, int count) +{ + if (vdma_debug) + printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count); + + r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count); +} + +/* + * Get Residual + */ +int vdma_get_residue(int channel) +{ + int residual; + + residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)); + + if (vdma_debug) + printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual); + + return residual; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c --- v2.1.43/linux/arch/mips/jazz/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/reset.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,24 @@ +/* + * linux/arch/mips/jazz/process.c + * + * Reset a Jazz machine. + */ +#include +#include +#include + +void jazz_machine_restart(char *command) +{ + printk("Implement jazz_machine_restart().\n"); + printk("Press reset to continue.\n"); + while(1); +} + +void jazz_machine_halt(void) +{ +} + +void jazz_machine_power_off(void) +{ + /* Jazz machines don't have a software power switch */ +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.1.43/linux/arch/mips/jazz/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/setup.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,73 @@ +/* + * Setup pointers to hardware dependand routines. + * + * 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) 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Initial irq handlers. + */ +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; + +extern asmlinkage void jazz_handle_int(void); +extern asmlinkage void jazz_fd_cacheflush(const void *addr, size_t size); +extern struct feature jazz_feature; + +extern void jazz_machine_restart(char *command); +extern void jazz_machine_halt(void); +extern void jazz_machine_power_off(void); + +__initfunc(static void jazz_irq_setup(void)) +{ + set_except_vector(0, jazz_handle_int); + 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 */ + r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ + set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); + /* set the clock to 100 Hz */ + r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); + request_region(0x20, 0x20, "pic1"); + request_region(0xa0, 0x20, "pic2"); + setup_x86_irq(2, &irq2); +} + +__initfunc(void jazz_setup(void)) +{ + irq_setup = jazz_irq_setup; + fd_cacheflush = jazz_fd_cacheflush; + feature = &jazz_feature; // Will go away + isa_slot_offset = 0xe3000000; + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); + /* The RTC is outside the port address space */ + + _machine_restart = jazz_machine_restart; + _machine_halt = jazz_machine_halt; + _machine_power_off = jazz_machine_power_off; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.1.43/linux/arch/mips/kernel/Makefile Sun Jul 14 23:55:11 1996 +++ linux/arch/mips/kernel/Makefile Thu Jun 26 12:33:37 1997 @@ -6,72 +6,44 @@ # unless it's something special (ie not a .c file). # -.S.s: - $(CPP) $(CFLAGS) $< -o $*.s .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -all: kernel.o head.o +all: kernel.o head.o init_task.o EXTRA_ASFLAGS = -mips3 -mcpu=r4000 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 +O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \ + ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \ + r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \ + r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o +OX_OBJS := mips_ksyms.o # -# Kernel debugging +# SGI's have very different interrupt/timer hardware. # -ifdef CONFIG_REMOTE_DEBUG -OBJS += gdb-low.o gdb-stub.o +ifndef CONFIG_SGI +O_OBJS += irq.o time.o endif # -# Board specific code +# Do we want to be able to execute IRIX elf binaries? # -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 +ifdef CONFIG_BINFMT_IRIX +O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o endif # -# CPU model specific code +# Kernel debugging # -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 information about CPU yet. -endif - -ifdef CONFIG_CPU_R8000 - exit 1 # no detailed information about CPU yet. +ifdef CONFIG_REMOTE_DEBUG +O_OBJS += gdb-low.o gdb-stub.o endif -ifdef CONFIG_CPU_R10000 -O_OBJS += r4xx0.o +# +# Depending from some other kernel option +# +ifdef CONFIG_PROC_FS +O_OBJS += proc.o endif # @@ -88,13 +60,23 @@ head.o: head.S -magnum4000.o: magnum4000.S - -pica.o: pica.S - -r4xx0.o: r4xx0.S - -tyne.o: tyne.S +#r4k_switch.o: r4k_switch.S +# +#r4k_misc.o: r4k_misc.S +# +#r4k_scall.o: r4k_scall.S +# +#r4k_fpu.o: r4k_fpu.S +# +#r2300_switch.o: r2300_switch.S +# +#r2300_misc.o: r2300_misc.S +# +#r2300_scall.o: r2300_scall.S +# +#r2300_fpu.o: r2300_fpu.S +# +#r6000_fpu.o: r6000_fpu.S clean: diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/bios32.c linux/arch/mips/kernel/bios32.c --- v2.1.43/linux/arch/mips/kernel/bios32.c Tue Jan 17 22:54:12 1995 +++ linux/arch/mips/kernel/bios32.c Wed Dec 31 16:00:00 1969 @@ -1,7 +0,0 @@ -/* - * bios 32 replacement - */ -unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) -{ - return memory_start; -} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/branch.c linux/arch/mips/kernel/branch.c --- v2.1.43/linux/arch/mips/kernel/branch.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/branch.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,196 @@ +/* + * Branch and jump emulation. + * + * 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) 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * Compute the return address and do emulate branch and instruction + * simulation, if required. + */ +int __compute_return_epc(struct pt_regs *regs) +{ + unsigned int *addr, bit, fcr31; + long epc; + union mips_instruction insn; + + epc = regs->cp0_epc; + if (epc & 3) { + printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); + force_sig(SIGBUS, current); + return -EFAULT; + } + + /* + * Read the instruction + */ + addr = (unsigned int *) (unsigned long) epc; + if (__get_user(insn.word, addr)) { + force_sig(SIGSEGV, current); + return -EFAULT; + } + + regs->regs[0] = 0; + switch (insn.i_format.opcode) { + /* + * jr and jalr are in r_format format. + */ + case spec_op: + switch (insn.r_format.func) { + case jalr_op: + regs->regs[insn.r_format.rd] = epc + 8; + /* Fall through */ + case jr_op: + regs->cp0_epc = regs->regs[insn.r_format.rs]; + break; + } + break; + + /* + * This group contains: + * bltz_op, bgez_op, bltzl_op, bgezl_op, + * bltzal_op, bgezal_op, bltzall_op, bgezall_op. + */ + case bcond_op: + switch (insn.i_format.rt) { + case bltz_op: + case bltzl_op: + if (regs->regs[insn.i_format.rs] < 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case bgez_op: + case bgezl_op: + if (regs->regs[insn.i_format.rs] >= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case bltzal_op: + case bltzall_op: + regs->regs[31] = epc + 8; + if (regs->regs[insn.i_format.rs] < 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case bgezal_op: + case bgezall_op: + regs->regs[31] = epc + 8; + if (regs->regs[insn.i_format.rs] >= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + } + break; + + /* + * These are unconditional and in j_format. + */ + case jal_op: + regs->regs[31] = regs->cp0_epc + 8; + case j_op: + epc += 4; + epc >>= 28; + epc <<= 28; + epc |= (insn.j_format.target << 2); + regs->cp0_epc = epc; + break; + + /* + * These are conditional and in i_format. + */ + case beq_op: + case beql_op: + if (regs->regs[insn.i_format.rs] == + regs->regs[insn.i_format.rt]) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case bne_op: + case bnel_op: + if (regs->regs[insn.i_format.rs] != + regs->regs[insn.i_format.rt]) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case blez_op: /* not really i_format */ + case blezl_op: + /* rt field assumed to be zero */ + if (regs->regs[insn.i_format.rs] <= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case bgtz_op: + case bgtzl_op: + /* rt field assumed to be zero */ + if (regs->regs[insn.i_format.rs] > 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + /* + * And now the FPA/cp1 branch instructions. + * + * FIXME: This will silently fail for MIPS IV cop1 branches with + * the cc field != 0. + */ + case cop1_op: + asm ("cfc1\t%0,$31":"=r" (fcr31)); + bit = (insn.i_format.rt >> 2); + bit += bit ? 24 : 23; + switch (insn.i_format.rt) { + case 0: /* bc1f */ + case 2: /* bc1fl */ + if (~fcr31 & (1 << bit)) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + + case 1: /* bc1t */ + case 3: /* bc1tl */ + if (fcr31 & (1 << bit)) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + regs->cp0_epc = epc; + break; + } + break; + } + + return 0; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.1.43/linux/arch/mips/kernel/entry.S Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/kernel/entry.S Thu Jun 26 12:33:37 1997 @@ -12,107 +12,85 @@ * 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. The ISA dependent TLB - * code is in arch/mips/kernel/.S + * code is in arch/mips//.S */ +#include #include #include +#include #include -#include #include #include #include #include #include #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 -exec_domain = 60 - -#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 + .set mips3 .align 4 +/* XXX cli/sti ??? */ handle_bottom_half: - 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) - ori t0,s3,0x1f + ori t0,s3, 0x1f xori t0,0x1e + jal do_bottom_half - mtc0 t0,CP0_STATUS # delay slot - mtc0 s3,CP0_STATUS # Restore old IRQ state + mtc0 t0,CP0_STATUS + b 9f - sw s1,%lo(intr_count)(s0) # delay slot + mtc0 s3,CP0_STATUS # Restore old IRQ state -reschedule: jal schedule - nop # delay slot -EXPORT(ret_from_sys_call) - lw t0,intr_count # bottom half - bnez t0,return +reschedule: + jal schedule + nop -9: lw t0,bh_mask # delay slot +EXPORT(ret_from_sys_call) + lw t0,bh_mask lw t1,bh_active # unused delay slot and t0,t1 bnez t0,handle_bottom_half +9: lw t0,PT_STATUS(sp) # returning to kernel mode? - lw t0,FR_STATUS(sp) # returning to kernel mode? - andi t1,t0,0x10 + andi t1,t0, 0x10 beqz t1,return # -> yes - - mfc0 t0,CP0_STATUS # delay slot - lw t1,need_resched - ori t0,0x1f # enable irqs - xori t0,0x1e + lw t1,need_resched bnez t1,reschedule - mtc0 t0,CP0_STATUS # delay slot - - lw s0,current + GET_CURRENT(s0) lw t0,task - lw a0,blocked(s0) + lw a0,TASK_BLOCKED(s0) + beq s0,t0,return # task[0] cannot have signals - # save blocked in a0 for - # signal handling - lw t0,signal(s0) + lw t0,TASK_SIGNAL(s0) + nor t1,zero,a0 and t1,t0,t1 beqz t1,return - nop + nop jal do_signal - move a1,sp # delay slot - + move a1,sp + .set noat -EXPORT(return) RESTORE_ALL - ERET +EXPORT(return) + RESTORE_ALL + eret .set at /* * Beware: interrupt, fast_interrupt and bad_interrupt have unusual * calling conventions to speedup the mess. * - * t1 - interrupt number + * a0 - interrupt number * s2 - destroyed * return values: * v0 - return routine @@ -120,145 +98,126 @@ .text .set at .align 5 -NESTED(interrupt, FR_SIZE, sp) +NESTED(interrupt, PT_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 - move a1,sp # delay slot + move a1,sp + mfc0 t0,CP0_STATUS # disable IRQs ori t0,1 xori t0,1 + mtc0 t0,CP0_STATUS + .set reorder la v0,ret_from_sys_call jr s2 - mtc0 t0,CP0_STATUS # delay slot + .set noreorder END(interrupt) .align 5 -NESTED(fast_interrupt, FR_SIZE, sp) +NESTED(fast_interrupt, PT_SIZE, sp) move s2,ra - move a0,t1 jal do_fast_IRQ - move a1,sp # delay slot - lui v0,%hi(return) + nop + + .set reorder + la v0,return jr s2 - addiu v0,%lo(return) # delay slot + .set noreorder END(fast_interrupt) -LEAF(bad_interrupt) /* * Don't return & unblock the pic */ +LEAF(bad_interrupt) j return - nop END(bad_interrupt) -/* - * 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 .text -NESTED(do_syscalls, 32, sp) - subu sp,32 - sw ra,28(sp) - sll a2,a2,PTRLOG - lw t0,dst(a2) - move t2,a1 - jalr t0 - lw t0,FR_REG29(a0) # get old user stack pointer - - .set reorder # for sake of R3000 -7: lw t1,24(t0) # parameter #7 from usp - sw t1,24(t0) -6: lw t1,20(t0) # parameter #6 from usp - sw t1,20(t0) -5: lw t1,16(t0) # parameter #5 from usp - sw t1,16(t0) - .set noreorder -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 - - .rdata - .align PTRLOG -dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b + .align 5 +LEAF(spurious_interrupt) + /* + * Someone tried to fool us by sending an interrupt but we + * couldn't find a cause for it. + */ + 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) /* * 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_clear_none(exception) +#define __BUILD_clear_fpe(exception) \ + cfc1 a1,fcr31; \ + li a2,~(0x3f<<12); \ + and a2,a1; \ + ctc1 a2,fcr31; +#define __BUILD_clear_ade(exception) \ + MFC0 t0,CP0_BADVADDR; \ + REG_S t0,PT_BVADDR(sp); #define __BUILD_silent(exception) + +#define fmt "Got %s at %016Lx.\n" + #define __BUILD_verbose(exception) \ la a1,8f; \ TEXT (#exception); \ - lw a2,FR_EPC(sp); \ - PRINT("Got %s at %08x.\n") + REG_L a2,PT_EPC(sp); \ + PRINT(fmt) #define __BUILD_count(exception) \ .set reorder; \ lw t0,exception_count_##exception; \ - addiu t0,1; \ + addiu t0, 1; \ sw t0,exception_count_##exception; \ .set noreorder; \ .data; \ EXPORT(exception_count_##exception); \ .word 0; \ - .text; -#define BUILD_HANDLER(exception,verbose) \ - .text; \ + .previous; +#define BUILD_HANDLER(exception,handler,clear,verbose) \ .align 5; \ - NESTED(handle_##exception, FR_SIZE, sp); \ + NESTED(handle_##exception, PT_SIZE, sp); \ .set noat; \ SAVE_ALL; \ + __BUILD_clear_##clear(exception); \ 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 */ \ + li t0,-1; /* not a sys call */ \ + REG_S t0,PT_OR2(sp); \ + jal do_##handler; \ + move a0,sp; \ j ret_from_sys_call; \ - nop; /* delay slot */ \ + nop; \ 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 */ + BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ + BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ + BUILD_HANDLER(ibe,ibe,none,verbose) /* #6 */ + BUILD_HANDLER(dbe,dbe,none,verbose) /* #7 */ + BUILD_HANDLER(sys,sys,none,silent) /* #8 */ + BUILD_HANDLER(bp,bp,none,silent) /* #9 */ + BUILD_HANDLER(ri,ri,none,silent) /* #10 */ + BUILD_HANDLER(cpu,cpu,none,silent) /* #11 */ + BUILD_HANDLER(ov,ov,none,silent) /* #12 */ + BUILD_HANDLER(tr,tr,none,silent) /* #13 */ + BUILD_HANDLER(vcei,vcei,none,verbose) /* #14 */ + BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */ + BUILD_HANDLER(watch,watch,none,verbose) /* #23 */ + BUILD_HANDLER(vced,vced,none,verbose) /* #31 */ + BUILD_HANDLER(reserved,reserved,none,verbose) /* others */ /* * Exception handler table with 32 entries. @@ -281,31 +240,43 @@ .data .align PTRLOG EXPORT(sys_call_table) - /* - * Reserved space for all the SVR4, SVR, BSD43 and POSIX - * flavoured syscalls. - */ - .space (__NR_Linux)*PTRSIZE - - /* - * Linux flavoured syscalls. - */ #define SYS(call, narg) PTR call + + /* Reserved space for all SVR4 syscalls. */ + .space (1000)*PTRSIZE + +#ifdef CONFIG_BINFMT_IRIX + /* 32bit IRIX5 system calls. */ +#include "irix5sys.h" +#else + .space (1000)*PTRSIZE /* No IRIX syscalls */ +#endif + + /* Reserved space for all the BSD43 and POSIX syscalls. */ + .space (2000)*PTRSIZE + + /* Linux flavoured syscalls. */ #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 + + /* Reserved space for all SVR4 flavoured syscalls. */ + .space (1000) + +#ifdef CONFIG_BINFMT_IRIX + /* 32bit IRIX5 system calls. */ +#include "irix5sys.h" +#else + .space (1000) /* No IRIX syscalls */ +#endif + + /* Reserved space for all the BSD43 and POSIX syscalls. */ + .space (2000) + + /* Linux flavoured syscalls. */ #include "syscalls.h" diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v2.1.43/linux/arch/mips/kernel/gdb-low.S Wed Dec 13 02:39:43 1995 +++ linux/arch/mips/kernel/gdb-low.S Thu Jun 26 12:33:37 1997 @@ -9,9 +9,9 @@ #include #include -#include #include #include +#include #include #include @@ -33,7 +33,8 @@ */ lui k1,%hi(kernelsp) lw k1,%lo(kernelsp)(k1) -1: move k0,sp +1: + move k0,sp subu sp,k1,GDB_FR_SIZE sw k0,GDB_FR_REG29(sp) sw v0,GDB_FR_REG2(sp) @@ -100,8 +101,9 @@ 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 + nop swc1 $0,GDB_FR_FPR0(sp) swc1 $1,GDB_FR_FPR1(sp) @@ -149,7 +151,8 @@ * current stack frame ptr */ -2: sw sp,GDB_FR_FRP(sp) +2: + sw sp,GDB_FR_FRP(sp) /* * CP0 registers (R4000/R4400 unused registers skipped) @@ -179,8 +182,9 @@ */ move a0,sp + jal handle_exception - nop + nop /* * restore all writable registers, in reverse order @@ -207,8 +211,9 @@ 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 + nop lwc1 $31,GDB_FR_FPR31(sp) lwc1 $30,GDB_FR_FPR30(sp) @@ -247,7 +252,8 @@ * Now the CP0 and integer registers */ -3: mfc0 t0,CP0_STATUS +3: + mfc0 t0,CP0_STATUS ori t0,0x1f xori t0,0x1f mtc0 t0,CP0_STATUS @@ -292,7 +298,7 @@ lw $1,GDB_FR_REG1(sp) lw sp,GDB_FR_REG29(sp) /* Deallocate stack */ - ERET + eret .set at .set reorder END(trap_low) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.1.43/linux/arch/mips/kernel/gdb-stub.c Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/kernel/gdb-stub.c Thu Jun 26 12:33:37 1997 @@ -70,7 +70,6 @@ #include #include -#include #include #include #include @@ -326,7 +325,10 @@ void set_debug_traps(void) { struct hard_trap_info *ht; + unsigned long flags; + unsigned char c; + save_flags(flags); cli(); for (ht = hard_trap_info; ht->tt && ht->signo; ht++) set_except_vector(ht->tt, trap_low); @@ -334,9 +336,14 @@ * In case GDB is started before us, ack any packets * (presumably "$?#xx") sitting there. */ + while((c = getDebugChar()) != '$'); + while((c = getDebugChar()) != '#'); + c = getDebugChar(); /* eat first csum byte */ + c = getDebugChar(); /* eat second csum byte */ + putDebugChar('+'); /* ack it */ - putDebugChar ('+'); initialized = 1; + restore_flags(flags); breakpoint(); } @@ -605,7 +612,7 @@ * NB: We flush both caches, just to be sure... */ - sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE); + flush_cache_all(); return; /* NOTREACHED */ break; diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.1.43/linux/arch/mips/kernel/head.S Mon May 6 02:26:03 1996 +++ linux/arch/mips/kernel/head.S Thu Jun 26 12:33:37 1997 @@ -1,258 +1,616 @@ /* * arch/mips/kernel/head.S * - * Copyright (C) 1994, 1995 Waldorf Electronics + * Copyright (C) 1994, 1995 Waldorf Electronics, 1996 Paul M. Antoine * Written by Ralf Baechle and Andreas Busse + * Modified for DECStation and hence R3000 support by Paul M. Antoine + * Further modifications by David S. Miller * * Head.S contains the MIPS exception handler and startup code. */ +#include #include #include -#include +#include +#include +#include +#include #include #include #include #include #include +#include -#define PAGE_SIZE 0x1000 + .text + /* + * Reserved space for exception handlers. + * Necessary for machines which link their kernels at KSEG0. + */ + .fill 512 +/* + * This is space for the interrupt handlers. + * After trap_init() they are located at virtual address KSEG0. + * + * These handlers much be written in a relocatable manner + * because based upon the cpu type an arbitrary one of the + * following pieces of code will be copied to the KSEG0 + * vector location. + */ + /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ + .set noreorder + .set noat + LEAF(except_vec0_r4000) + .set mips3 + mfc0 k0, CP0_BADVADDR # Get faulting address + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 # get pgd only bits + lw k1, THREAD_PGDIR(k1) # get task pg_dir + sll k0, k0, 2 + addu k1, k1, k0 # add in pgd offset + mfc0 k0, CP0_CONTEXT # get context reg + lw k1, (k1) + srl k0, k0, 1 # get pte offset + and k0, k0, 0xff8 + addu k1, k1, k0 # add in offset + lw k0, 0(k1) # get even pte + lw k1, 4(k1) # get odd pte + srl k0, k0, 6 # convert to entrylo0 + mtc0 k0, CP0_ENTRYLO0 # load it + srl k1, k1, 6 # convert to entrylo1 + mtc0 k1, CP0_ENTRYLO1 # load it + b 1f + tlbwr # write random tlb entry +1: + nop + eret # return from trap + END(except_vec0_r4000) + + /* TLB refill, EXL == 0, R4600 version */ + LEAF(except_vec0_r4600) + .set mips3 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xff8 + addu k1, k1, k0 + lw k0, 0(k1) + lw k1, 4(k1) + srl k0, k0, 6 + mtc0 k0, CP0_ENTRYLO0 + srl k1, k1, 6 + mtc0 k1, CP0_ENTRYLO1 + nop + tlbwr + nop + eret + END(except_vec0_r4600) + + /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ + LEAF(except_vec0_r45k_bvahwbug) + .set mips3 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xff8 + addu k1, k1, k0 + lw k0, 0(k1) + lw k1, 4(k1) + tlbp + srl k0, k0, 6 + mtc0 k0, CP0_ENTRYLO0 + srl k1, k1, 6 + mfc0 k0, CP0_INDEX + mtc0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r45k_bvahwbug) + +#ifdef __SMP__ + /* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */ + LEAF(except_vec0_r4k_mphwbug) + .set mips3 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xff8 + addu k1, k1, k0 + lw k0, 0(k1) + lw k1, 4(k1) + tlbp + srl k0, k0, 6 + mtc0 k0, CP0_ENTRYLO0 + srl k1, k1, 6 + mfc0 k0, CP0_INDEX + mtc0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_mphwbug) +#endif + + /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */ + LEAF(except_vec0_r4k_250MHZhwbug) + .set mips3 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xff8 + addu k1, k1, k0 + lw k0, 0(k1) + lw k1, 4(k1) + srl k0, k0, 6 + mtc0 zero, CP0_ENTRYLO0 + mtc0 k0, CP0_ENTRYLO0 + srl k1, k1, 6 + mtc0 zero, CP0_ENTRYLO1 + mtc0 k1, CP0_ENTRYLO1 + b 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_250MHZhwbug) + +#ifdef __SMP__ + /* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */ + LEAF(except_vec0_r4k_MP250MHZhwbug) + .set mips3 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xff8 + addu k1, k1, k0 + lw k0, 0(k1) + lw k1, 4(k1) + tlbp + srl k0, k0, 6 + mtc0 zero, CP0_ENTRYLO0 + mtc0 k0, CP0_ENTRYLO0 + mfc0 k0, CP0_INDEX + srl k1, k1, 6 + mtc0 zero, CP0_ENTRYLO1 + mtc0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_MP250MHZhwbug) +#endif -#define MODE_GLOBAL 0x0001 /* shared for all processes */ -#define MODE_ALIAS 0x0016 /* uncachable */ + /* TLB refill, EXL == 0, R[23]00 version */ + LEAF(except_vec0_r2300) + .set mips1 + mfc0 k0, CP0_BADVADDR + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 + lw k1, THREAD_PGDIR(k1) + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + srl k0, k0, 1 + and k0, k0, 0xffc + addu k1, k1, k0 + lw k0, (k1) + srl k0, k0, 12 + mtc0 k0, CP0_ENTRYLO0 + mfc0 k1, CP0_EPC + tlbwr + nop + nop + nop + nop + jr k1 + rfe + END(except_vec0_r2300) + + + /* XTLB refill, EXL == 0, R4xx0 cpus only use this... */ + NESTED(except_vec1_generic, 0, sp) + .set noat + .set mips3 + /* Register saving is delayed as long as we don't know + * which registers really need to be saved. + */ + mfc0 k1, CP0_CONTEXT + dsra k1, 1 + lwu k0, (k1) # May cause another 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 # Needed for R4[04]00 pipeline + tlbwr + nop # Needed for R4[04]00 pipeline + nop + nop + eret + nop /* Workaround for R4000 bug. */ + eret + END(except_vec1_generic) + + /* Cache Error */ + LEAF(except_vec2_generic) + /* Famous last words: unreached */ + mfc0 a1,CP0_ERROREPC + PRINT("Cache error exception: c0_errorepc == %08x\n") +1: + j 1b + nop + END(except_vec2_generic) + + /* General exception vector R4000 version. */ + NESTED(except_vec3_r4000, 0, sp) + .set noat + mfc0 k1, CP0_CAUSE + + /* XXX Have to check for VCE's _before_ we do a load or store. */ + + la k0, exception_handlers + andi k1, k1, 0x7c + addu k0, k0, k1 + lw k0, (k0) + nop + jr k0 + nop + END(except_vec3_r4000) + .set at + + /* General exception vector. */ + NESTED(except_vec3_generic, 0, sp) + .set noat + mfc0 k1, CP0_CAUSE + la k0, exception_handlers + andi k1, k1, 0x7c + addu k0, k0, k1 + lw k0, (k0) + nop + jr k0 + nop + END(except_vec3_generic) + .set at + +/* + * Kernel entry point + */ +NESTED(kernel_entry, 16, sp) + .set noreorder + /* The following two symbols are used for kernel profiling. */ + EXPORT(stext) + EXPORT(_stext) + + /* Determine which MIPS variant we are running on. */ + b cpu_probe + nop + +probe_done: + +#ifndef CONFIG_SGI + /* Get the memory upper limit the bootloader passed to us + * in a0 + */ + la t0, mips_memory_upper + nop + sw a0, (t0) +#else + /* On SGI's the firmware/bootloader passes argc/argp/envp + * to us as arguments. But clear bss first because + * the romvec and other important info is stored there + * by prom_init(). + */ + la t0, _edata + sw zero, (t0) + la t1, (_end - 4) +1: + addiu t0, 4 + bne t0, t1, 1b + sw zero, (t0) - .text - .set mips3 -/* - * This is space for the interrupt handlers. - * They are located at virtual address KSEG[01] (physical 0x0) - */ - /* - * TLB refill, EXL == 0 - */ - .set noreorder - .set noat - LEAF(except_vec0) - dmfc0 k1,CP0_CONTEXT - dsra k1,1 - lwu k0,(k1) # May cause another 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 # 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 is so obscure that it will almost - * never happen. Well, but Mips writes about its bugs. - */ - nop - eret - END(except_vec0) - - /* - * XTLB refill, EXL == 0 - * Should never be reached - */ - .org except_vec0+0x80 - LEAF(except_vec1) - PANIC("XTLB Refill exception.\n") -1: j 1b - nop - END(except_vec1) - - /* - * Cache Error - */ - .org except_vec1+0x80 - LEAF(except_vec2) - /* - * Famous last words: unreached - */ - mfc0 a1,CP0_ERROREPC - PRINT("Cache error exception: c0_errorepc == %08x\n") -1: j 1b - nop - END(except_vec2) - - /* - * General exception vector. - */ - .org except_vec2+0x80 - 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. - */ - mfc0 k1,CP0_CAUSE - 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,0x7c - addu k0,k1 - lw k0,(k0) - NOP - jr k0 - nop - END(except_vec3) - .set at - -/******************************************************************************/ - -/* - * Kernel entry - */ - .set noreorder - NESTED(kernel_entry, 16, sp) - /* - * The following two symbols are used for kernel profiling. - */ - EXPORT(stext) - EXPORT(_stext) - -#ifdef CONF_DISABLE_KSEG0_CACHING - /* - * Disable all caching for KSEG0. This option is useful - * when cache trouble with drivers is suspected - */ - mfc0 t0,CP0_CONFIG - ori t0,7 - xori t0,5 - mtc0 t0,CP0_CONFIG + jal prom_init /* prom_init(argc, argv, envp); */ + nop #endif - /* - * Clear BSS first so that there are no surprises... - */ - la t0,_edata - la t1,_end - sw zero,(t0) -1: addiu t0,4 - bnel t0,t1,1b - sw zero,(t0) - - /* - * Initialize low level part of memory management - * First flush the TLB to make sure that we don't get a - * TLB shutdown during wire_mappings. - */ - jal tlbflush - mtc0 zero,CP0_WIRED # delay slot - jal wire_mappings - nop - - /* - * Stack for kernel and init - */ - 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 - nop # delay slot - /* - * Main should never return here, but - * just in case, we know what happens. - */ - b 1b - nop # delay slot - END(kernel_entry) - -/* - * wire_mappings - used to map hardware registers - */ - LEAF(wire_mappings) - /* - * Get base address of map0 table for the - * the board we're running on - */ - la t0,boot_info - lw t1,OFFSET_BOOTINFO_MACHTYPE(t0) - la t0,map0table - sll t1,PTRLOG # machtype used as index - addu t0,t1 - lw t0,(t0) # get base address - - /* - * Get number of wired TLB entries and - * loop over selected map0 table. - */ - lw t1,(t0) # number of wired TLB entries - move t2,zero # TLB entry counter - addiu t3,t1,1 # wire one additional entry - beqz t1,2f # null, exit - mtc0 t3,CP0_WIRED # delay slot - 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,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 - addiu t0,32 - bne t1,t2,1b # next TLB entry - tlbwi # delay slot - - /* - * We use only 4k pages. Therefore the PageMask register - * is expected to be setup for 4k pages. - */ -2: li t0,PM_4K - mtc0 t0,CP0_PAGEMASK - - /* - * Now map the pagetables - */ - mtc0 zero,CP0_INDEX - la t0,TLB_ROOT - dmtc0 t0,CP0_ENTRYHI - la t0,swapper_pg_dir-KSEG1 - srl t0,6 - ori t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid - dmtc0 t0,CP0_ENTRYLO0 - 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 will - * NEVER be changed. - */ - li t0,TLBMAP - dsll t0,1 - dmtc0 t0,CP0_CONTEXT - jr ra # delay slot - nop - END(wire_mappings) + /* Get the very one tags we need early in the boot process */ + nop + jal bi_EarlySnarf + nop +#ifndef CONFIG_SGI + /* Clear BSS first so that there are no surprises... */ + la t0, _edata + la t1, (_end - 4) + sw zero, (t0) +1: + addiu t0, 4 + bne t0, t1, 1b + sw zero, (t0) + nop +#endif + /* + * Determine the mmu/cache attached to this machine, + * then flush the tlb and caches. On the r4xx0 + * variants this also sets CP0_WIRED to zero. + */ + jal loadmmu + nop + + la t2, mips_cputype + lw t4, (t2) + li t1, CPU_R2000 + li t2, CPU_R3000 + li t3, CPU_R3000A + beq t4,t1,2f + nop + + beq t4,t2,2f + nop + + beq t4,t3,2f + nop + + jal wire_mappings_r4xx0 + nop + + b 9f + nop + +2: + jal wire_mappings_r3000 + nop + + /* + * Stack for kernel and init + */ +9: la sp, init_task_union+(KERNEL_STACK_SIZE-4*SZREG) + sw sp, kernelsp + + /* Disable coprocessors */ + mfc0 t0, CP0_STATUS + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX) + and t0, t1 + li t1, ST0_CU0 + or t0, ST0_CU0 + mtc0 t0, CP0_STATUS + +1: jal start_kernel + nop + /* + * Main should never return here, but + * just in case, we know what happens. + */ + b 1b + nop # delay slot + END(kernel_entry) + +/* + * wire_mappings - used to map hardware registers, r4xx0 version. + */ +LEAF(wire_mappings_r4xx0) + mtc0 zero, CP0_WIRED + nop + nop + nop + j ra + nop + END(wire_mappings_r4xx0) + +/* + * R3000 version of wire_mappings. + */ +LEAF(wire_mappings_r3000) + /* + * Get base address of map0 table for the + * the board we're running on + */ + lw t1, mips_machtype + la t0, map0table + sll t1, PTRLOG # machtype used as index + addu t0, t1 + lw t0, (t0) # get base address + nop + /* Get number of wired TLB entries and + * loop over selected map0 table. + */ + lw t1, (t0) # number of wired TLB entries + move t2, zero # TLB entry counter + addiu t3, t1, 1 # wire one additional entry + beqz t1, 2f # null, exit + nop + + addiu t0, 8 +1: + lw t4, 24(t0) # PageMask + ld t5, 0(t0) # entryHi + ld t6, 8(t0) # entryLo0 + addiu t2, 1 # increment ctr + mtc0 t2, CP0_INDEX # set TLB entry + nop + mtc0 t5, CP0_ENTRYHI + nop + mtc0 t6, CP0_ENTRYLO0 + addiu t0, 32 + bne t1, t2, 1b # next TLB entry + tlbwi + + /* We use only 4k pages. Therefore the PageMask register + * is expected to be setup for 4k pages. + */ +2: + /* Now map the pagetables */ + mtc0 zero, CP0_INDEX + la t0, TLB_ROOT + mtc0 t0, CP0_ENTRYHI + nop + la t0, swapper_pg_dir + srl t0, 12 + ori t0, (0x00e0|0x0100) # uncachable, dirty, valid + mtc0 t0, CP0_ENTRYLO0 + nop + tlbwi # delayed + + /* Load the context register with zero. To see why, look + * at how the tlb refill code above works. + */ + mtc0 zero, CP0_CONTEXT + + jr ra + nop + END(wire_mappings_r3000) + + /* CPU type probing code, called at Kernel entry. */ + LEAF(cpu_probe) + mfc0 t0, CP0_PRID + la t3, mips_cputype + andi t1, t0, 0xff00 + li t2, PRID_IMP_R2000 + bne t1, t2, 1f + andi t0, 0x00ff + + li t2, CPU_R2000 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R3000 + bne t1, t2, 1f + nop + + li t2, PRID_REV_R3000A + bne t0, t2, 9f + nop + + li t2, CPU_R3000A + b probe_done + sw t2, (t3) +9: + li t2, CPU_R3000 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R6000 + bne t1, t2, 1f + nop + + li t2, CPU_R6000 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R4000 + bne t1, t2, 1f + nop + + li t2, PRID_REV_R4400 + bne t0, t2, 9f + nop + + li t2, CPU_R4400SC + b probe_done + sw t2, (t3) +9: + li t2, CPU_R4000SC + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R6000A + bne t1, t2, 1f + nop + + li t2, CPU_R6000A + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R10000 + bne t1, t2, 1f + nop + + li t2, CPU_R10000 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R8000 + bne t1, t2, 1f + nop + + li t2, CPU_R8000 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R4600 + bne t1, t2, 1f + nop + + li t2, CPU_R4600 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R4700 + bne t1, t2, 1f + nop + + li t2, CPU_R4700 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R4650 + bne t1, t2, 1f + nop + + li t2, CPU_R4650 + b probe_done + sw t2, (t3) +1: + li t2, PRID_IMP_R5000 + bne t1, t2, 1f + nop + + li t2, CPU_R5000 + b probe_done + sw t2, (t3) +1: + li t2, CPU_UNKNOWN + sw t2, (t3) + + b probe_done + nop + END(cpu_probe) - .data + .data /* * Build an entry for table of wired entries */ @@ -269,6 +627,11 @@ * following by EntryHi/EntryLo pairs and page mask. * Since everything must be quad-aligned (8) we insert * some dummy zeros. + * + * Keep in mind that the PFN does not depend on the page size in the + * TLB page mask register. See milo's lib/dumptlb.c for how to decode + * and encode these entries. Don't see the same routine in the linux + * kernel distribution, since it is older and unreliable. */ /* @@ -282,19 +645,25 @@ PTR map0_tyne # Deskstation Tyne PTR map0_pica61 # Acer Pica-61 PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030) + PTR map0_dummy + PTR map0_dummy # DEC Personal DECStation 5000/2x (for now) + PTR map0_sni_rm200_pci # SNI RM200 PCI + PTR map0_dummy # SGI INDY map0_dummy: .word 0 # 0 entries .align 3 /* - * Initial mappings for Deskstation rPC boards. - * RB: Untested goodie - I don't have such a board. + * Deskstation rpc44 mappings. This machine has its EISA bus at physical + * address 0xa0000000 which we map for 32M, but that doesn't match EISA + * spec. Not sure what to do about this. Its I/O ports are memory mapped + * at physical memory location 0xb0000000. */ map0_rpc: .word 2 # no. of wired TLB entries .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 +MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M) # ISA Memory space +MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K) # ISA I/O Space /* * Initial mappings for Deskstation Tyne boards. @@ -330,51 +699,52 @@ * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-) * FIXME: Remove or merge some of the mappings. */ - map0_magnum4000: .word 8 # no. wired TLB entries .word 0 # dummy -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 +MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K) # 0 +MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # 1 local I/O +MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # 2 IRQ source +MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # 3 local video ctrl +MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # 4 ext. video ctrl +MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # 5 local video mem. +MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # 6 ISA I/O and mem. +MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # 7 PCR +/* + * The RM200 doesn't need any wired entries. + */ +map0_sni_rm200_pci: + .word 0 # no. wired TLB entries + .word 0 # dummy .text .org 0x1000 - .globl swapper_pg_dir -swapper_pg_dir = . + (KSEG1-KSEG0) + EXPORT(swapper_pg_dir) -/* - * The page tables are initialized to only 4MB here - the final page - * tables are set up later depending on memory size. - */ .org 0x2000 - EXPORT(pg0) - - .org 0x3000 EXPORT(empty_bad_page) - .org 0x4000 + .org 0x3000 EXPORT(empty_bad_page_table) - .org 0x5000 + .org 0x4000 EXPORT(empty_zero_page) - .org 0x6000 + .org 0x5000 EXPORT(invalid_pte_table) - .org 0x7000 + .org 0x6000 + /* + * init_task_union follows here in the .text segment. + * Keep this aligned to a 8kb boundary! + */ + .data EXPORT(cache_error_buffer) .fill 32*4,1,0 - .data EXPORT(kernelsp) PTR 0 diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c --- v2.1.43/linux/arch/mips/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/init_task.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,22 @@ +#include +#include + +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +/* + * Initial task structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by making sure + * the linker maps this in the .text segment right after head.S, + * and making head.S ensure the proper alignment. + * + * The things we do for performance.. + */ +union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ioport.c linux/arch/mips/kernel/ioport.c --- v2.1.43/linux/arch/mips/kernel/ioport.c Wed Dec 13 02:39:43 1995 +++ linux/arch/mips/kernel/ioport.c Thu Jun 26 12:33:37 1997 @@ -15,8 +15,6 @@ return -ENOSYS; } -unsigned int *stack; - /* * sys_iopl has to be used when you want to access the IO ports * beyond the 0x3ff range: to get the full 65536 ports bitmapped diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c --- v2.1.43/linux/arch/mips/kernel/ipc.c Sun Jan 26 02:07:05 1997 +++ linux/arch/mips/kernel/ipc.c Thu Jun 26 12:33:37 1997 @@ -2,11 +2,9 @@ * linux/arch/mips/kernel/ipc.c * * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/i386 + * have a non-standard calling sequence on the Linux/MIPS * platform. */ - -#include #include #include #include @@ -16,17 +14,16 @@ #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. + * This is really horribly ugly. FIXME: Get rid of this wrapper. */ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) { -#ifdef CONFIG_SYSVIPC int version, ret; lock_kernel(); @@ -46,9 +43,9 @@ ret = -EINVAL; if (!ptr) goto out; - if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))) - goto out; - fourth.__pad = (void *) get_fs_long(ptr); + ret = -EFAULT; + if (get_user(fourth.__pad, (void **) ptr)) + goto out; ret = sys_semctl (first, second, third, fourth); goto out; } @@ -66,12 +63,13 @@ switch (version) { case 0: { struct ipc_kludge tmp; + ret = -EINVAL; if (!ptr) - return -EINVAL; - if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))) goto out; - memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr, - sizeof (tmp)); + ret = -EFAULT; + if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, + sizeof (tmp))) + goto out; ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); goto out; } @@ -95,15 +93,12 @@ switch (version) { case 0: default: { ulong raddr; - if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) - goto out; ret = sys_shmat (first, (char *) ptr, second, &raddr); if (ret) goto out; - put_fs_long (raddr, (ulong *) third); - ret = 0; + ret = put_user (raddr, (ulong *) third); goto out; - } + } case 1: /* iBCS2 emulator entry point */ ret = -EINVAL; if (get_fs() != get_ds()) @@ -129,7 +124,4 @@ out: unlock_kernel(); return ret; -#else /* CONFIG_SYSVIPC */ - return -ENOSYS; -#endif /* CONFIG_SYSVIPC */ } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.1.43/linux/arch/mips/kernel/irix5sys.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/irix5sys.h Thu Jun 26 12:33:37 1997 @@ -0,0 +1,1024 @@ +/* $Id: irix5sys.h,v 1.1 1997/06/06 09:32:29 ralf Exp $ + * irix5sys.h: 32-bit IRIX5 ABI system call table. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +/* 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. + */ + +/* Keys: + * V == Valid and should work as expected for most cases. + * HV == Half Valid, some things will work, some likely will not + * IV == InValid, certainly will not work at all yet + * ?V == ?'ably Valid, I have not done enough looking into it + * DC == Don't Care, a rats ass we couldn't give + */ + +SYS(sys_syscall, 0) /* 1000 sysindir() V*/ +SYS(sys_exit, 1) /* 1001 exit() V*/ +SYS(sys_fork, 0) /* 1002 fork() V*/ +SYS(sys_read, 3) /* 1003 read() V*/ +SYS(sys_write, 3) /* 1004 write() V*/ +SYS(sys_open, 3) /* 1005 open() V*/ +SYS(sys_close, 1) /* 1006 close() V*/ +SYS(irix_unimp, 0) /* 1007 (XXX IRIX 4 wait) V*/ +SYS(sys_creat, 2) /* 1008 creat() V*/ +SYS(sys_link, 2) /* 1009 link() V*/ +SYS(sys_unlink, 1) /* 1010 unlink() V*/ +SYS(irix_exec, 0) /* 1011 exec() V*/ +SYS(sys_chdir, 1) /* 1012 chdir() V*/ +SYS(irix_gtime, 0) /* 1013 time() V*/ +SYS(irix_unimp, 0) /* 1014 (XXX IRIX 4 mknod) V*/ +SYS(sys_chmod, 2) /* 1015 chmod() V*/ +SYS(irix_chown, 3) /* 1016 chown() V*/ +SYS(irix_brk, 1) /* 1017 break() V*/ +SYS(irix_unimp, 0) /* 1018 (XXX IRIX 4 stat) V*/ +SYS(sys_lseek, 3) /* 1019 lseek() XXX64bit HV*/ +SYS(irix_getpid, 0) /* 1020 getpid() V*/ +SYS(irix_mount, 6) /* 1021 mount() IV*/ +SYS(sys_umount, 1) /* 1022 umount() V*/ +SYS(sys_setuid, 1) /* 1023 setuid() V*/ +SYS(irix_getuid, 0) /* 1024 getuid() V*/ +SYS(irix_stime, 1) /* 1025 stime() V*/ +SYS(irix_unimp, 4) /* 1026 XXX ptrace() IV*/ +SYS(irix_alarm, 1) /* 1027 alarm() V*/ +SYS(irix_unimp, 0) /* 1028 (XXX IRIX 4 fstat) V*/ +SYS(irix_pause, 0) /* 1029 pause() V*/ +SYS(sys_utime, 2) /* 1030 utime() V*/ +SYS(irix_unimp, 0) /* 1031 nuthin' V*/ +SYS(irix_unimp, 0) /* 1032 nobody home man... V*/ +SYS(sys_access, 2) /* 1033 access() V*/ +SYS(sys_nice, 1) /* 1034 nice() V*/ +SYS(irix_statfs, 2) /* 1035 statfs() V*/ +SYS(sys_sync, 0) /* 1036 sync() V*/ +SYS(sys_kill, 2) /* 1037 kill() V*/ +SYS(irix_fstatfs, 2) /* 1038 fstatfs() V*/ +SYS(irix_setpgrp, 1) /* 1039 setpgrp() V*/ +SYS(irix_syssgi, 0) /* 1040 syssgi() HV*/ +SYS(sys_dup, 1) /* 1041 dup() V*/ +SYS(sys_pipe, 0) /* 1042 pipe() V*/ +SYS(irix_times, 1) /* 1043 times() V*/ +SYS(irix_unimp, 0) /* 1044 XXX profil() IV*/ +SYS(irix_unimp, 0) /* 1045 XXX lock() IV*/ +SYS(sys_setgid, 1) /* 1046 setgid() V*/ +SYS(irix_getgid, 0) /* 1047 getgid() V*/ +SYS(irix_unimp, 0) /* 1048 (XXX IRIX 4 ssig) V*/ +SYS(irix_msgsys, 6) /* 1049 sys_msgsys V*/ +SYS(sys_sysmips, 4) /* 1050 sysmips() HV*/ +SYS(irix_unimp, 0) /* 1051 XXX sysacct() IV*/ +SYS(irix_shmsys, 5) /* 1052 sys_shmsys V*/ +SYS(irix_semsys, 0) /* 1053 sys_semsys V*/ +SYS(irix_ioctl, 3) /* 1054 ioctl() HV*/ +SYS(irix_uadmin, 0) /* 1055 XXX sys_uadmin() HC*/ +SYS(irix_sysmp, 0) /* 1056 sysmp() HV*/ +SYS(irix_utssys, 4) /* 1057 sys_utssys() HV*/ +SYS(irix_unimp, 0) /* 1058 nada enchilada V*/ +SYS(irix_exece, 0) /* 1059 exece() V*/ +SYS(sys_umask, 1) /* 1060 umask() V*/ +SYS(sys_chroot, 1) /* 1061 chroot() V*/ +SYS(irix_fcntl, 3) /* 1062 fcntl() ?V*/ +SYS(irix_ulimit, 2) /* 1063 ulimit() HV*/ +SYS(irix_unimp, 0) /* 1064 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1065 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1066 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1067 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1068 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1069 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1070 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1071 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1072 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1073 XXX AFS shit DC*/ +SYS(irix_unimp, 0) /* 1074 nuttin' V*/ +SYS(irix_unimp, 0) /* 1075 XXX sys_getrlimit64()IV*/ +SYS(irix_unimp, 0) /* 1076 XXX sys_setrlimit64()IV*/ +SYS(sys_nanosleep, 2) /* 1077 nanosleep() V*/ +SYS(irix_lseek64, 5) /* 1078 lseek64() ?V*/ +SYS(sys_rmdir, 1) /* 1079 rmdir() V*/ +SYS(sys_mkdir, 2) /* 1080 mkdir() V*/ +SYS(sys_getdents, 3) /* 1081 getdents() V*/ +SYS(irix_sginap, 1) /* 1082 sys_sginap() V*/ +SYS(irix_sgikopt, 3) /* 1083 sys_sgikopt() DC*/ +SYS(sys_sysfs, 3) /* 1084 sysfs() ?V*/ +SYS(irix_unimp, 0) /* 1085 XXX sys_getmsg() DC*/ +SYS(irix_unimp, 0) /* 1086 XXX sys_putmsg() DC*/ +SYS(sys_poll, 3) /* 1087 poll() V*/ +SYS(irix_sigreturn, 0) /* 1088 sigreturn() ?V*/ +SYS(sys_accept, 3) /* 1089 accept() V*/ +SYS(sys_bind, 3) /* 1090 bind() V*/ +SYS(sys_connect, 3) /* 1091 connect() V*/ +SYS(irix_gethostid, 0) /* 1092 sys_gethostid() ?V*/ +SYS(sys_getpeername, 3) /* 1093 getpeername() V*/ +SYS(sys_getsockname, 3) /* 1094 getsockname() V*/ +SYS(sys_getsockopt, 5) /* 1095 getsockopt() V*/ +SYS(sys_listen, 2) /* 1096 listen() V*/ +SYS(sys_recv, 4) /* 1097 recv() V*/ +SYS(sys_recvfrom, 6) /* 1098 recvfrom() V*/ +SYS(sys_recvmsg, 3) /* 1099 recvmsg() V*/ +SYS(sys_select, 5) /* 1100 select() V*/ +SYS(sys_send, 4) /* 1101 send() V*/ +SYS(sys_sendmsg, 3) /* 1102 sendmsg() V*/ +SYS(sys_sendto, 6) /* 1103 sendto() V*/ +SYS(irix_sethostid, 1) /* 1104 sys_sethostid() ?V*/ +SYS(sys_setsockopt, 5) /* 1105 setsockopt() V*/ +SYS(sys_shutdown, 2) /* 1106 shutdown() ?V*/ +SYS(irix_socket, 3) /* 1107 socket() V*/ +SYS(sys_gethostname, 2) /* 1108 sys_gethostname() ?V*/ +SYS(sys_sethostname, 2) /* 1109 sethostname() ?V*/ +SYS(irix_getdomainname, 2) /* 1110 sys_getdomainname() ?V*/ +SYS(sys_setdomainname, 2) /* 1111 setdomainname() ?V*/ +SYS(sys_truncate, 2) /* 1112 truncate() V*/ +SYS(sys_ftruncate, 2) /* 1113 ftruncate() V*/ +SYS(sys_rename, 2) /* 1114 rename() V*/ +SYS(sys_symlink, 2) /* 1115 symlink() V*/ +SYS(sys_readlink, 3) /* 1116 readlink() V*/ +SYS(irix_unimp, 0) /* 1117 XXX IRIX 4 lstat() DC*/ +SYS(irix_unimp, 0) /* 1118 nothin' V*/ +SYS(irix_unimp, 0) /* 1119 XXX nfs_svc() DC*/ +SYS(irix_unimp, 0) /* 1120 XXX nfs_getfh() DC*/ +SYS(irix_unimp, 0) /* 1121 XXX async_daemon() DC*/ +SYS(irix_unimp, 0) /* 1122 XXX exportfs() DC*/ +SYS(sys_setregid, 2) /* 1123 setregid() V*/ +SYS(sys_setreuid, 2) /* 1124 setreuid() V*/ +SYS(sys_getitimer, 2) /* 1125 getitimer() V*/ +SYS(sys_setitimer, 3) /* 1126 setitimer() V*/ +SYS(irix_unimp, 1) /* 1127 XXX adjtime() IV*/ +SYS(irix_gettimeofday, 1) /* 1128 gettimeofday() V*/ +SYS(irix_unimp, 0) /* 1129 XXX sproc() IV*/ +SYS(irix_prctl, 0) /* 1130 prctl() HV*/ +SYS(irix_unimp, 0) /* 1131 XXX procblk() IV*/ +SYS(irix_unimp, 0) /* 1132 XXX sprocsp() IV*/ +SYS(irix_unimp, 0) /* 1133 XXX sgigsc() IV*/ +SYS(irix_mmap32, 6) /* 1134 mmap() XXXflags? ?V*/ +SYS(sys_munmap, 2) /* 1135 munmap() V*/ +SYS(sys_mprotect, 3) /* 1136 mprotect() V*/ +SYS(sys_msync, 4) /* 1137 msync() V*/ +SYS(irix_madvise, 3) /* 1138 madvise() DC*/ +SYS(irix_pagelock, 3) /* 1139 pagelock() IV*/ +SYS(irix_getpagesize, 0) /* 1140 getpagesize() V*/ +SYS(irix_quotactl, 0) /* 1141 quotactl() V*/ +SYS(irix_unimp, 0) /* 1142 nobody home man V*/ +SYS(sys_getpgid, 1) /* 1143 BSD getpgrp() V*/ +SYS(irix_BSDsetpgrp, 2) /* 1143 BSD setpgrp() V*/ +SYS(sys_vhangup, 0) /* 1144 vhangup() V*/ +SYS(sys_fsync, 1) /* 1145 fsync() V*/ +SYS(sys_fchdir, 1) /* 1146 fchdir() V*/ +SYS(sys_getrlimit, 2) /* 1147 getrlimit() ?V*/ +SYS(sys_setrlimit, 2) /* 1148 setrlimit() ?V*/ +SYS(sys_cacheflush, 3) /* 1150 cacheflush() HV*/ +SYS(sys_cachectl, 3) /* 1151 cachectl() HV*/ +SYS(sys_fchown, 3) /* 1152 fchown() ?V*/ +SYS(sys_fchmod, 2) /* 1153 fchmod() ?V*/ +SYS(irix_unimp, 0) /* 1154 XXX IRIX 4 wait3() V*/ +SYS(sys_socketpair, 4) /* 1155 socketpair() V*/ +SYS(irix_systeminfo, 3) /* 1156 systeminfo() IV*/ +SYS(irix_uname, 1) /* 1157 uname() IV*/ +SYS(irix_xstat, 3) /* 1158 xstat() V*/ +SYS(irix_lxstat, 3) /* 1159 lxstat() V*/ +SYS(irix_fxstat, 3) /* 1160 fxstat() V*/ +SYS(irix_xmknod, 0) /* 1161 xmknod() ?V*/ +SYS(irix_sigaction, 4) /* 1162 sigaction() ?V*/ +SYS(irix_sigpending, 1) /* 1163 sigpending() ?V*/ +SYS(irix_sigprocmask, 3) /* 1164 sigprocmask() ?V*/ +SYS(irix_sigsuspend, 0) /* 1165 sigsuspend() ?V*/ +SYS(irix_sigpoll_sys, 3) /* 1166 sigpoll_sys() IV*/ +SYS(irix_swapctl, 2) /* 1167 swapctl() IV*/ +SYS(irix_getcontext, 0) /* 1168 getcontext() HV*/ +SYS(irix_setcontext, 0) /* 1169 setcontext() HV*/ +SYS(irix_waitsys, 5) /* 1170 waitsys() IV*/ +SYS(irix_sigstack, 2) /* 1171 sigstack() HV*/ +SYS(irix_sigaltstack, 2) /* 1172 sigaltstack() HV*/ +SYS(irix_sigsendset, 2) /* 1173 sigsendset() IV*/ +SYS(irix_statvfs, 2) /* 1174 statvfs() V*/ +SYS(irix_fstatvfs, 2) /* 1175 fstatvfs() V*/ +SYS(irix_unimp, 0) /* 1176 XXX getpmsg() DC*/ +SYS(irix_unimp, 0) /* 1177 XXX putpmsg() DC*/ +SYS(irix_lchown, 3) /* 1178 lchown() V*/ +SYS(irix_priocntl, 0) /* 1179 priocntl() DC*/ +SYS(irix_sigqueue, 4) /* 1180 sigqueue() IV*/ +SYS(sys_readv, 3) /* 1181 readv() V*/ +SYS(sys_writev, 3) /* 1182 writev() V*/ +SYS(irix_truncate64, 4) /* 1183 truncate64() XX32bit HV*/ +SYS(irix_ftruncate64, 4) /* 1184 ftruncate64()XX32bit HV*/ +SYS(irix_mmap64, 0) /* 1185 mmap64() XX32bit HV*/ +SYS(irix_dmi, 0) /* 1186 dmi() DC*/ +SYS(irix_pread, 6) /* 1187 pread() IV*/ +SYS(irix_pwrite, 6) /* 1188 pwrite() IV*/ +SYS(sys_fsync, 1) /* 1189 fdatasync() XXPOSIX HV*/ +SYS(irix_sgifastpath, 7) /* 1190 sgifastpath() WHEEE IV*/ +SYS(irix_unimp, 0) /* 1191 XXX attr_get() DC*/ +SYS(irix_unimp, 0) /* 1192 XXX attr_getf() DC*/ +SYS(irix_unimp, 0) /* 1193 XXX attr_set() DC*/ +SYS(irix_unimp, 0) /* 1194 XXX attr_setf() DC*/ +SYS(irix_unimp, 0) /* 1195 XXX attr_remove() DC*/ +SYS(irix_unimp, 0) /* 1196 XXX attr_removef() DC*/ +SYS(irix_unimp, 0) /* 1197 XXX attr_list() DC*/ +SYS(irix_unimp, 0) /* 1198 XXX attr_listf() DC*/ +SYS(irix_unimp, 0) /* 1199 XXX attr_multi() DC*/ +SYS(irix_unimp, 0) /* 1200 XXX attr_multif() DC*/ +SYS(irix_statvfs64, 2) /* 1201 statvfs64() V*/ +SYS(irix_fstatvfs64, 2) /* 1202 fstatvfs64() V*/ +SYS(irix_getmountid, 2) /* 1203 getmountid()XXXfsids HV*/ +SYS(irix_nsproc, 5) /* 1204 nsproc() IV*/ +SYS(irix_getdents64, 3) /* 1205 getdents64() HV*/ +SYS(irix_unimp, 0) /* 1206 XXX DFS garbage DC*/ +SYS(irix_ngetdents, 4) /* 1207 ngetdents() XXXeop HV*/ +SYS(irix_ngetdents64, 4) /* 1208 ngetdents64() XXXeop HV*/ +SYS(irix_unimp, 0) /* 1209 nothin' V*/ +SYS(irix_unimp, 0) /* 1210 XXX pidsprocsp() */ +SYS(irix_unimp, 0) /* 1211 XXX rexec() */ +SYS(irix_unimp, 0) /* 1212 XXX timer_create() */ +SYS(irix_unimp, 0) /* 1213 XXX timer_delete() */ +SYS(irix_unimp, 0) /* 1214 XXX timer_settime() */ +SYS(irix_unimp, 0) /* 1215 XXX timer_gettime() */ +SYS(irix_unimp, 0) /* 1216 XXX timer_setoverrun() */ +SYS(sys_sched_rr_get_interval, 2) /* 1217 sched_rr_get_interval()V*/ +SYS(sys_sched_yield, 0) /* 1218 sched_yield() V*/ +SYS(sys_sched_getscheduler, 1) /* 1219 sched_getscheduler() V*/ +SYS(sys_sched_setscheduler, 3) /* 1220 sched_setscheduler() V*/ +SYS(sys_sched_getparam, 2) /* 1221 sched_getparam() V*/ +SYS(sys_sched_setparam, 2) /* 1222 sched_setparam() V*/ +SYS(irix_unimp, 0) /* 1223 XXX usync_cntl() */ +SYS(irix_unimp, 0) /* 1224 XXX psema_cntl() */ +SYS(irix_unimp, 0) /* 1225 XXX restartreturn() */ + +/* Just to pad things out nicely. */ +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) +SYS(irix_unimp, 0) + +/* YEEEEEEEEEEEEEEEEEE!!!! */ diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.1.43/linux/arch/mips/kernel/irixelf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/irixelf.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,1365 @@ +/* + * irixelf.c: Code to load IRIX ELF executables which conform to + * the MIPS ABI. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Based upon work which is: + * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define DLINFO_ITEMS 12 + +#include + +#undef DEBUG_ELF + +static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs); +static int load_irix_library(int fd); +static int irix_core_dump(long signr, struct pt_regs * regs); +extern int dump_fpu (elf_fpregset_t *); + +static struct linux_binfmt irix_format = { +#ifndef MODULE + NULL, NULL, load_irix_binary, load_irix_library, irix_core_dump +#else + NULL, &__this_module.usecount, load_irix_binary, load_irix_library, irix_core_dump +#endif +}; + +#ifdef DEBUG_ELF +/* Debugging routines. */ +static char *get_elf_p_type(Elf32_Word p_type) +{ + int i = (int) p_type; + + switch(i) { + case PT_NULL: return("PT_NULL"); break; + case PT_LOAD: return("PT_LOAD"); break; + case PT_DYNAMIC: return("PT_DYNAMIC"); break; + case PT_INTERP: return("PT_INTERP"); break; + case PT_NOTE: return("PT_NOTE"); break; + case PT_SHLIB: return("PT_SHLIB"); break; + case PT_PHDR: return("PT_PHDR"); break; + case PT_LOPROC: return("PT_LOPROC/REGINFO"); break; + case PT_HIPROC: return("PT_HIPROC"); break; + default: return("PT_BOGUS"); break; + } +} + +static void print_elfhdr(struct elfhdr *ehp) +{ + int i; + + printk("ELFHDR: e_ident<"); + for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]); + printk("%x>\n", ehp->e_ident[i]); + printk(" e_type[%04x] e_machine[%04x] e_version[%08lx]\n", + (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine, + (unsigned long) ehp->e_version); + printk(" e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] " + "e_flags[%08lx]\n", + (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff, + (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags); + printk(" e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n", + (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize, + (unsigned short) ehp->e_phnum); + printk(" e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n", + (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum, + (unsigned short) ehp->e_shstrndx); +} + +static void print_phdr(int i, struct elf_phdr *ep) +{ + printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] " + "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type), + (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr, + (unsigned long) ep->p_paddr); + printk(" p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] " + "p_align[%08lx]\n", (unsigned long) ep->p_filesz, + (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags, + (unsigned long) ep->p_align); +} + +static void dump_phdrs(struct elf_phdr *ep, int pnum) +{ + int i; + + for(i = 0; i < pnum; i++, ep++) { + if((ep->p_type == PT_LOAD) || + (ep->p_type == PT_INTERP) || + (ep->p_type == PT_PHDR)) + print_phdr(i, ep); + } +} +#endif /* (DEBUG_ELF) */ + +static void set_brk(unsigned long start, unsigned long end) +{ + start = PAGE_ALIGN(start); + end = PAGE_ALIGN(end); + if (end <= start) + return; + do_mmap(NULL, start, end - start, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); +} + + +/* We need to explicitly zero any fractional pages + * after the data section (i.e. bss). This would + * contain the junk from the file that should not + * be in memory. + */ +static void padzero(unsigned long elf_bss) +{ + unsigned long nbyte; + + nbyte = elf_bss & (PAGE_SIZE-1); + if (nbyte) { + nbyte = PAGE_SIZE - nbyte; + clear_user((void *) elf_bss, nbyte); + } +} + +unsigned long * create_irix_tables(char * p, int argc, int envc, + struct elfhdr * exec, unsigned int load_addr, + unsigned int interp_load_addr, + struct pt_regs *regs, struct elf_phdr *ephdr) +{ + char **argv, **envp; + unsigned long *sp; + unsigned long *csp; + +#ifdef DEBUG_ELF + printk("create_irix_tables: p[%p] argc[%d] envc[%d] " + "load_addr[%08x] interp_load_addr[%08x]\n", + p, argc, envc, load_addr, interp_load_addr); +#endif + sp = (unsigned long *) (0xfffffffc & (unsigned long) p); + + /* Make sure we will be aligned properly at the end of this. */ + csp = sp; + csp -= exec ? DLINFO_ITEMS*2 : 2; + csp -= envc + 1; + csp -= argc+1; + if (!(((unsigned long) csp) & 4)) + sp--; + + sp -= exec ? DLINFO_ITEMS*2 : 2; + sp -= envc+1; + envp = (char **) sp; + sp -= argc+1; + argv = (char **) sp; + + __put_user((unsigned long)argc, --sp); + +#define NEW_AUX_ENT(nr, id, val) \ + __put_user ((id), sp+(nr*2)); \ + __put_user ((val), sp+(nr*2+1)); \ + +#define INTERP_ALIGN (~((64 * 1024) - 1)) + + NEW_AUX_ENT (0, AT_NULL, 0); + if(exec) { + struct elf_phdr * eppnt; + eppnt = (struct elf_phdr *) exec->e_phoff; + + /* Put this here for an ELF program interpreter */ + NEW_AUX_ENT (0, AT_PHDR, ephdr->p_vaddr); + NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr)); + NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum); + NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE); + NEW_AUX_ENT (4, AT_BASE, (interp_load_addr & (INTERP_ALIGN))); + NEW_AUX_ENT (5, AT_FLAGS, 0); + NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry); + NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid); + NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid); + NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid); + NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid); + } +#undef NEW_AUX_ENT + + current->mm->arg_start = (unsigned long) p; + while (argc-->0) { + __put_user(p, argv++); + p += strlen_user(p); + } + __put_user(NULL, argv); + current->mm->arg_end = current->mm->env_start = (unsigned long) p; + while (envc-->0) { + __put_user(p, envp++); + p += strlen_user(p); + } + __put_user(NULL, envp); + current->mm->env_end = (unsigned long) p; + return sp; +} + + +/* This is much more generalized than the library routine read function, + * so we keep this separate. Technically the library read function + * is only provided so that we can read a.out libraries that have + * an ELF header. + */ +static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, + struct inode * interpreter_inode, + unsigned int *interp_load_addr) +{ + struct file * file; + struct elf_phdr *elf_phdata = NULL; + struct elf_phdr *eppnt; + unsigned int len; + unsigned int load_addr; + int elf_exec_fileno; + int elf_bss; + int retval; + unsigned int last_bss; + int error; + int i; + unsigned int k; + + elf_bss = 0; + last_bss = 0; + error = load_addr = 0; + +#ifdef DEBUG_ELF + print_elfhdr(interp_elf_ex); +#endif + + /* First of all, some simple consistency checks */ + if((interp_elf_ex->e_type != ET_EXEC && + interp_elf_ex->e_type != ET_DYN) || + !elf_check_arch(interp_elf_ex->e_machine) || + (!interpreter_inode->i_op || + !interpreter_inode->i_op->default_file_ops->mmap)){ + printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type); + return 0xffffffff; + } + + /* Now read in all of the header information */ + if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) { + printk("IRIX interp header bigger than a page (%d)\n", + (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum)); + return 0xffffffff; + } + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, + GFP_KERNEL); + + if(!elf_phdata) { + printk("Cannot kmalloc phdata for IRIX interp.\n"); + return 0xffffffff; + } + + /* If the size of this structure has changed, then punt, since + * we will be doing the wrong thing. + */ + if(interp_elf_ex->e_phentsize != 32) { + printk("IRIX interp e_phentsize == %d != 32 ", + interp_elf_ex->e_phentsize); + kfree(elf_phdata); + return 0xffffffff; + } + + retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, + (char *) elf_phdata, + sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1); + +#ifdef DEBUG_ELF + dump_phdrs(elf_phdata, interp_elf_ex->e_phnum); +#endif + + elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY); + if (elf_exec_fileno < 0) { + printk("Could not open IRIX interp inode.\n"); + kfree(elf_phdata); + return 0xffffffff; + } + + file = current->files->fd[elf_exec_fileno]; + + eppnt = elf_phdata; + for(i=0; ie_phnum; i++, eppnt++) { + if(eppnt->p_type == PT_LOAD) { + int elf_type = MAP_PRIVATE | MAP_DENYWRITE; + int elf_prot = 0; + unsigned long vaddr = 0; + if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; + if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; + if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + elf_type |= MAP_FIXED; + vaddr = eppnt->p_vaddr; + +#ifdef DEBUG_ELF + printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", + file, vaddr, + (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), + (unsigned long) elf_prot, (unsigned long) elf_type, + (unsigned long) (eppnt->p_offset & 0xfffff000)); +#endif + error = do_mmap(file, vaddr, + eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), + elf_prot, elf_type, + eppnt->p_offset & 0xfffff000); + + if(error < 0 && error > -1024) { + printk("Aieee IRIX interp mmap error=%d\n", error); + break; /* Real error */ + } +#ifdef DEBUG_ELF + printk("error=%08lx ", (unsigned long) error); +#endif + if(!load_addr && interp_elf_ex->e_type == ET_DYN) { + load_addr = error; +#ifdef DEBUG_ELF + printk("load_addr = error "); +#endif + } + + /* Find the end of the file mapping for this phdr, and keep + * track of the largest address we see for this. + */ + k = eppnt->p_vaddr + eppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + + /* Do the same thing for the memory mapping - between + * elf_bss and last_bss is the bss section. + */ + k = eppnt->p_memsz + eppnt->p_vaddr; + if(k > last_bss) last_bss = k; +#ifdef DEBUG_ELF + printk("\n"); +#endif + } + } + + /* Now use mmap to map the library into memory. */ + sys_close(elf_exec_fileno); + if(error < 0 && error > -1024) { +#ifdef DEBUG_ELF + printk("got error %d\n", error); +#endif + kfree(elf_phdata); + return 0xffffffff; + } + + /* Now fill out the bss section. First pad the last page up + * to the page boundary, and then perform a mmap to make sure + * that there are zeromapped pages up to and including the last + * bss page. + */ +#ifdef DEBUG_ELF + printk("padzero(%08lx) ", (unsigned long) (elf_bss)); +#endif + padzero(elf_bss); + len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ + +#ifdef DEBUG_ELF + printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss, + (unsigned long) len); +#endif + + /* Map the last of the bss segment */ + if (last_bss > len) { + do_mmap(NULL, len, (last_bss - len), + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + } + kfree(elf_phdata); + + *interp_load_addr = load_addr; + return ((unsigned int) interp_elf_ex->e_entry); +} + +/* Check sanity of IRIX elf executable header. */ +static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm) +{ + if (ehp->e_ident[0] != 0x7f || strncmp(&ehp->e_ident[1], "ELF", 3)) { + return -ENOEXEC; + } + + /* First of all, some simple consistency checks */ + if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || + !elf_check_arch(ehp->e_machine) || + (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || + !bprm->inode->i_op->default_file_ops->mmap)) { + return -ENOEXEC; + } + + /* Only support MIPS ARCH2 or greater IRIX binaries for now. */ + if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) { + return -ENOEXEC; + } + + /* XXX Don't support N32 or 64bit binaries yet because they can + * XXX and do execute 64 bit instructions and expect all registers + * XXX to be 64 bit as well. We need to make the kernel save + * XXX all registers as 64bits on cpu's capable of this at + * XXX exception time plus frob the XTLB exception vector. + */ + if((ehp->e_flags & 0x20)) { + return -ENOEXEC; + } + + return 0; /* It's ok. */ +} + +#define IRIX_INTERP_PREFIX "/usr/gnemul/irix" + +/* Look for an IRIX ELF interpreter. */ +static inline int look_for_irix_interpreter(char **name, + struct inode **interpreter_inode, + struct elfhdr *interp_elf_ex, + struct elf_phdr *epp, + struct linux_binprm *bprm, int pnum) +{ + int i, old_fs; + int retval = -EINVAL; + + *name = NULL; + for(i = 0; i < pnum; i++, epp++) { + if(epp->p_type != PT_INTERP) + continue; + + /* It is illegal to have two interpreters for one executable. */ + if(*name != NULL) + goto losing; + + *name = (char *) kmalloc((epp->p_filesz + + strlen(IRIX_INTERP_PREFIX)), + GFP_KERNEL); + if(!*name) + return -ENOMEM; + + strcpy(*name, IRIX_INTERP_PREFIX); + retval = read_exec(bprm->inode, epp->p_offset, (*name + 16), + epp->p_filesz, 1); + if(retval < 0) + goto losing; + + old_fs = get_fs(); set_fs(get_ds()); + retval = namei(*name, interpreter_inode); + set_fs(old_fs); + if(retval < 0) + goto losing; + + retval = read_exec(*interpreter_inode, 0, bprm->buf, 128, 1); + if(retval < 0) + goto losing; + + *interp_elf_ex = *((struct elfhdr *) bprm->buf); + } + return 0; + +losing: + kfree(*name); + return retval; +} + +static inline int verify_irix_interpreter(struct elfhdr *ihp) +{ + if(ihp->e_ident[0] != 0x7f || strncmp(&ihp->e_ident[1], "ELF", 3)) + return -ELIBBAD; + return 0; +} + +#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE) + +static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum, + unsigned int *estack, unsigned int *laddr, + unsigned int *scode, unsigned int *ebss, + unsigned int *ecode, unsigned int *edata, + unsigned int *ebrk) +{ + unsigned int tmp; + int i, prot; + + for(i = 0; i < pnum; i++, epp++) { + if(epp->p_type != PT_LOAD) + continue; + + /* Map it. */ + prot = (epp->p_flags & PF_R) ? PROT_READ : 0; + prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0; + prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0; + (void) do_mmap(fp, (epp->p_vaddr & 0xfffff000), + (epp->p_filesz + (epp->p_vaddr & 0xfff)), + prot, EXEC_MAP_FLAGS, + (epp->p_offset & 0xfffff000)); + + /* Fixup location tracking vars. */ + if((epp->p_vaddr & 0xfffff000) < *estack) + *estack = (epp->p_vaddr & 0xfffff000); + if(!*laddr) + *laddr = epp->p_vaddr - epp->p_offset; + if(epp->p_vaddr < *scode) + *scode = epp->p_vaddr; + + tmp = epp->p_vaddr + epp->p_filesz; + if(tmp > *ebss) + *ebss = tmp; + if((epp->p_flags & PF_X) && *ecode < tmp) + *ecode = tmp; + if(*edata < tmp) + *edata = tmp; + + tmp = epp->p_vaddr + epp->p_memsz; + if(tmp > *ebrk) + *ebrk = tmp; + } + +} + +static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, + struct inode *iino, unsigned int *iladdr, + int pnum, int old_fs, + unsigned int *eentry) +{ + int i; + + *eentry = 0xffffffff; + for(i = 0; i < pnum; i++, epp++) { + if(epp->p_type != PT_INTERP) + continue; + + /* We should have fielded this error elsewhere... */ + if(*eentry != 0xffffffff) + return -1; + + set_fs(old_fs); + *eentry = load_irix_interp(ihp, iino, iladdr); + old_fs = get_fs(); + set_fs(get_ds()); + + iput(iino); + + if(*eentry == 0xffffffff) + return -1; + } + return 0; +} + +/* These are the functions used to load ELF style executables and shared + * libraries. There is no binary dependent code anywhere else. + */ +static inline int do_load_irix_binary(struct linux_binprm * bprm, + struct pt_regs * regs) +{ + struct elfhdr elf_ex, interp_elf_ex; + struct inode *interpreter_inode; + struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr; + unsigned int load_addr, elf_bss, elf_brk; + unsigned int elf_entry, interp_load_addr = 0; + unsigned int start_code, end_code, end_data, elf_stack; + int old_fs, elf_exec_fileno, retval, has_interp, has_ephdr, i; + char *elf_interpreter; + + load_addr = 0; + has_interp = has_ephdr = 0; + elf_ihdr = elf_ephdr = 0; + elf_ex = *((struct elfhdr *) bprm->buf); + + if(verify_binary(&elf_ex, bprm)) + return -ENOEXEC; + +#ifdef DEBUG_ELF + print_elfhdr(&elf_ex); +#endif + + /* Now read in all of the header information */ + elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * + elf_ex.e_phnum, GFP_KERNEL); + if (elf_phdata == NULL) + return -ENOMEM; + + retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata, + elf_ex.e_phentsize * elf_ex.e_phnum, 1); + if (retval < 0) { + kfree (elf_phdata); + return retval; + } + +#ifdef DEBUG_ELF + dump_phdrs(elf_phdata, elf_ex.e_phnum); +#endif + + /* Set some things for later. */ + for(i = 0; i < elf_ex.e_phnum; i++) { + switch(elf_phdata[i].p_type) { + case PT_INTERP: + has_interp = 1; + elf_ihdr = &elf_phdata[i]; + break; + case PT_PHDR: + has_ephdr = 1; + elf_ephdr = &elf_phdata[i]; + break; + }; + } +#ifdef DEBUG_ELF + printk("\n"); +#endif + + elf_bss = 0; + elf_brk = 0; + elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); + + if (elf_exec_fileno < 0) { + kfree (elf_phdata); + return elf_exec_fileno; + } + + elf_stack = 0xffffffff; + elf_interpreter = NULL; + start_code = 0xffffffff; + end_code = 0; + end_data = 0; + + retval = look_for_irix_interpreter(&elf_interpreter, &interpreter_inode, + &interp_elf_ex, elf_phdata, bprm, + elf_ex.e_phnum); + if(retval) { + kfree(elf_phdata); + sys_close(elf_exec_fileno); + return retval; + } + + if(elf_interpreter) { + retval = verify_irix_interpreter(&interp_elf_ex); + if(retval) { + kfree(elf_interpreter); + kfree(elf_phdata); + sys_close(elf_exec_fileno); + return retval; + } + } + + /* OK, we are done with that, now set up the arg stuff, + * and then start this sucker up. + */ + if (!bprm->sh_bang) { + if (!bprm->p) { + if(elf_interpreter) { + kfree(elf_interpreter); + } + kfree (elf_phdata); + sys_close(elf_exec_fileno); + return -E2BIG; + } + } + + /* OK, This is the point of no return. */ + flush_old_exec(bprm); + + current->mm->end_data = 0; + current->mm->end_code = 0; + current->mm->start_mmap = ELF_START_MMAP; + current->mm->mmap = NULL; + elf_entry = (unsigned int) elf_ex.e_entry; + + /* Do this so that we can load the interpreter, if need be. We will + * change some of these later. + */ + current->mm->rss = 0; + bprm->p = setup_arg_pages(bprm->p, bprm); + current->mm->start_stack = bprm->p; + + /* At this point, we assume that the image should be loaded at + * fixed address, not at a variable address. + */ + old_fs = get_fs(); + set_fs(get_ds()); + + map_executable(current->files->fd[elf_exec_fileno], elf_phdata, + elf_ex.e_phnum, &elf_stack, &load_addr, + &start_code, &elf_bss, &end_code, &end_data, &elf_brk); + + if(elf_interpreter) { + retval = map_interpreter(elf_phdata, &interp_elf_ex, + interpreter_inode, &interp_load_addr, + elf_ex.e_phnum, old_fs, &elf_entry); + kfree(elf_interpreter); + if(retval) { + set_fs(old_fs); + printk("Unable to load IRIX ELF interpreter\n"); + kfree(elf_phdata); + send_sig(SIGSEGV, current, 0); + return 0; + } + } + + set_fs(old_fs); + + kfree(elf_phdata); + sys_close(elf_exec_fileno); + current->personality = PER_IRIX32; + + if (current->exec_domain && current->exec_domain->module) + __MOD_DEC_USE_COUNT(current->exec_domain->module); + if (current->binfmt && current->binfmt->module) + __MOD_DEC_USE_COUNT(current->binfmt->module); + current->exec_domain = lookup_exec_domain(current->personality); + current->binfmt = &irix_format; + if (current->exec_domain && current->exec_domain->module) + __MOD_INC_USE_COUNT(current->exec_domain->module); + if (current->binfmt && current->binfmt->module) + __MOD_INC_USE_COUNT(current->binfmt->module); + + current->suid = current->euid = current->fsuid = bprm->e_uid; + current->sgid = current->egid = current->fsgid = bprm->e_gid; + current->flags &= ~PF_FORKNOEXEC; + bprm->p = (unsigned long) + create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc, + (elf_interpreter ? &elf_ex : NULL), + load_addr, interp_load_addr, regs, elf_ephdr); + current->mm->start_brk = current->mm->brk = elf_brk; + current->mm->end_code = end_code; + current->mm->start_code = start_code; + current->mm->end_data = end_data; + current->mm->start_stack = bprm->p; + + /* Calling set_brk effectively mmaps the pages that we need for the + * bss and break sections. + */ + set_brk(elf_bss, elf_brk); + + padzero(elf_bss); + +#ifdef DEBUG_ELF + printk("(start_brk) %08lx\n" , current->mm->start_brk); + printk("(end_code) %08lx\n" , current->mm->end_code); + printk("(start_code) %08lx\n" , current->mm->start_code); + printk("(end_data) %08lx\n" , current->mm->end_data); + printk("(start_stack) %08lx\n" , current->mm->start_stack); + printk("(brk) %08lx\n" , current->mm->brk); +#endif + +#if 0 /* XXX No fucking way dude... */ + /* Why this, you ask??? Well SVr4 maps page 0 as read-only, + * and some applications "depend" upon this behavior. + * Since we do not have the power to recompile these, we + * emulate the SVr4 behavior. Sigh. + */ + (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); +#endif + + start_thread(regs, elf_entry, bprm->p); + if (current->flags & PF_PTRACED) + send_sig(SIGTRAP, current, 0); + return 0; +} + +static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) +{ + int retval; + + MOD_INC_USE_COUNT; + retval = do_load_irix_binary(bprm, regs); + MOD_DEC_USE_COUNT; + return retval; +} + +/* This is really simpleminded and specialized - we are loading an + * a.out library that is given an ELF header. + */ +static inline int do_load_irix_library(int fd) +{ + struct file * file; + struct elfhdr elf_ex; + struct elf_phdr *elf_phdata = NULL; + struct inode * inode; + unsigned int len; + int elf_bss; + int retval; + unsigned int bss; + int error; + int i,j, k; + + len = 0; + file = current->files->fd[fd]; + inode = file->f_inode; + elf_bss = 0; + + if (!file || !file->f_op) + return -EACCES; + + /* Seek to the beginning of the file. */ + if (file->f_op->llseek) { + if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0) + return -ENOEXEC; + } else + file->f_pos = 0; + + set_fs(KERNEL_DS); + error = file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)); + set_fs(USER_DS); + if (error != sizeof(elf_ex)) + return -ENOEXEC; + + if (elf_ex.e_ident[0] != 0x7f || + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) + return -ENOEXEC; + + /* First of all, some simple consistency checks. */ + if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || + !elf_check_arch(elf_ex.e_machine) || + (!inode->i_op || !inode->i_op->default_file_ops->mmap)) + return -ENOEXEC; + + /* Now read in all of the header information. */ + if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) + return -ENOEXEC; + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); + if (elf_phdata == NULL) + return -ENOMEM; + + retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata, + sizeof(struct elf_phdr) * elf_ex.e_phnum, 1); + + j = 0; + for(i=0; ip_type == PT_LOAD) j++; + + if(j != 1) { + kfree(elf_phdata); + return -ENOEXEC; + } + + while(elf_phdata->p_type != PT_LOAD) elf_phdata++; + + /* Now use mmap to map the library into memory. */ + error = do_mmap(file, + elf_phdata->p_vaddr & 0xfffff000, + elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, + elf_phdata->p_offset & 0xfffff000); + + k = elf_phdata->p_vaddr + elf_phdata->p_filesz; + if(k > elf_bss) elf_bss = k; + + if (error != (elf_phdata->p_vaddr & 0xfffff000)) { + kfree(elf_phdata); + return error; + } + + padzero(elf_bss); + + len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; + bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; + if (bss > len) + do_mmap(NULL, len, bss-len, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + kfree(elf_phdata); + return 0; +} + +static int load_irix_library(int fd) +{ + int retval; + + MOD_INC_USE_COUNT; + retval = do_load_irix_library(fd); + MOD_DEC_USE_COUNT; + return retval; +} + +/* Called through irix_syssgi() to map an elf image given an FD, + * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many + * phdrs there are in the USER_PHDRP array. We return the vaddr the + * first phdr was successfully mapped to. + */ +unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) +{ + struct elf_phdr *hp; + struct file *filp; + int i, retval; + +#ifdef DEBUG_ELF + printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n", + fd, user_phdrp, cnt); +#endif + + /* First get the verification out of the way. */ + hp = user_phdrp; + retval = verify_area(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt)); + if(retval) { +#ifdef DEBUG_ELF + printk("irix_mapelf: verify_area fails!\n"); +#endif + return retval; + } + +#ifdef DEBUG_ELF + dump_phdrs(user_phdrp, cnt); +#endif + + for(i = 0; i < cnt; i++, hp++) + if(hp->p_type != PT_LOAD) { + printk("irix_mapelf: One section is not PT_LOAD!\n"); + return -ENOEXEC; + } + + filp = current->files->fd[fd]; + if(!filp || !filp->f_op) { + printk("irix_mapelf: Bogon filp!\n"); + return -EACCES; + } + + hp = user_phdrp; + for(i = 0; i < cnt; i++, hp++) { + int prot; + + prot = (hp->p_flags & PF_R) ? PROT_READ : 0; + prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0; + prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0; + retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000), + (hp->p_filesz + (hp->p_vaddr & 0xfff)), + prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), + (hp->p_offset & 0xfffff000)); + + if(retval != (hp->p_vaddr & 0xfffff000)) { + printk("irix_mapelf: do_mmap fails with %d!\n", retval); + return retval; + } + } + +#ifdef DEBUG_ELF + printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr); +#endif + return user_phdrp->p_vaddr; +} + +/* + * ELF core dumper + * + * Modelled on fs/exec.c:aout_core_dump() + * Jeremy Fitzhardinge + */ + +/* These are the only things you should do on a core-file: use only these + * functions to write out all the necessary info. + */ +static int dump_write(struct file *file, const void *addr, int nr) +{ + return file->f_op->write(file->f_inode, file, addr, nr) == nr; +} + +static int dump_seek(struct file *file, off_t off) +{ + if (file->f_op->llseek) { + if (file->f_op->llseek(file->f_inode, file, off, 0) != off) + return 0; + } else + file->f_pos = off; + return 1; +} + +/* Decide whether a segment is worth dumping; default is yes to be + * sure (missing info is worse than too much; etc). + * Personally I'd include everything, and use the coredump limit... + * + * I think we should skip something. But I am not sure how. H.J. + */ +static inline int maydump(struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC))) + return 0; +#if 1 + if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN)) + return 1; + if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED)) + return 0; +#endif + return 1; +} + +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) + +/* An ELF note in memory. */ +struct memelfnote +{ + const char *name; + int type; + unsigned int datasz; + void *data; +}; + +static int notesize(struct memelfnote *en) +{ + int sz; + + sz = sizeof(struct elf_note); + sz += roundup(strlen(en->name), 4); + sz += roundup(en->datasz, 4); + + return sz; +} + +/* #define DEBUG */ + +#define DUMP_WRITE(addr, nr) \ + do { if (!dump_write(file, (addr), (nr))) return 0; } while(0) +#define DUMP_SEEK(off) \ + do { if (!dump_seek(file, (off))) return 0; } while(0) + +static int writenote(struct memelfnote *men, struct file *file) +{ + struct elf_note en; + + en.n_namesz = strlen(men->name); + en.n_descsz = men->datasz; + en.n_type = men->type; + + DUMP_WRITE(&en, sizeof(en)); + DUMP_WRITE(men->name, en.n_namesz); + /* XXX - cast from long long to long to avoid need for libgcc.a */ + DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ + DUMP_WRITE(men->data, men->datasz); + DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ + + return 1; +} +#undef DUMP_WRITE +#undef DUMP_SEEK + +#define DUMP_WRITE(addr, nr) \ + if (!dump_write(&file, (addr), (nr))) \ + goto close_coredump; +#define DUMP_SEEK(off) \ + if (!dump_seek(&file, (off))) \ + goto close_coredump; +/* Actual dumper. + * + * This is a two-pass process; first we find the offsets of the bits, + * and then they are actually written out. If we run out of core limit + * we just truncate. + */ +static int irix_core_dump(long signr, struct pt_regs * regs) +{ + int has_dumped = 0; + struct file file; + struct inode *inode; + unsigned short fs; + char corefile[6+sizeof(current->comm)]; + int segs; + int i; + size_t size; + struct vm_area_struct *vma; + struct elfhdr elf; + off_t offset = 0, dataoff; + int limit = current->rlim[RLIMIT_CORE].rlim_cur; + int numnote = 4; + struct memelfnote notes[4]; + struct elf_prstatus prstatus; /* NT_PRSTATUS */ + elf_fpregset_t fpu; /* NT_PRFPREG */ + struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ + + if (!current->dumpable || limit < PAGE_SIZE) + return 0; + current->dumpable = 0; + +#ifndef CONFIG_BINFMT_IRIX + MOD_INC_USE_COUNT; +#endif + + /* Count what's needed to dump, up to the limit of coredump size. */ + segs = 0; + size = 0; + for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { + if (maydump(vma)) + { + int sz = vma->vm_end-vma->vm_start; + + if (size+sz >= limit) + break; + else + size += sz; + } + + segs++; + } +#ifdef DEBUG + printk("irix_core_dump: %d segs taking %d bytes\n", segs, size); +#endif + + /* Set up header. */ + memcpy(elf.e_ident, ELFMAG, SELFMAG); + elf.e_ident[EI_CLASS] = ELFCLASS32; + elf.e_ident[EI_DATA] = ELFDATA2LSB; + elf.e_ident[EI_VERSION] = EV_CURRENT; + memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); + + elf.e_type = ET_CORE; + elf.e_machine = ELF_ARCH; + elf.e_version = EV_CURRENT; + elf.e_entry = 0; + elf.e_phoff = sizeof(elf); + elf.e_shoff = 0; + elf.e_flags = 0; + elf.e_ehsize = sizeof(elf); + elf.e_phentsize = sizeof(struct elf_phdr); + elf.e_phnum = segs+1; /* Include notes. */ + elf.e_shentsize = 0; + elf.e_shnum = 0; + elf.e_shstrndx = 0; + + fs = get_fs(); + set_fs(KERNEL_DS); + memcpy(corefile,"core.",5); +#if 0 + memcpy(corefile+5,current->comm,sizeof(current->comm)); +#else + corefile[4] = '\0'; +#endif + if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) { + inode = NULL; + goto end_coredump; + } + if (!S_ISREG(inode->i_mode)) + goto end_coredump; + if (!inode->i_op || !inode->i_op->default_file_ops) + goto end_coredump; + file.f_mode = 3; + file.f_flags = 0; + file.f_count = 1; + file.f_inode = inode; + file.f_pos = 0; + file.f_reada = 0; + file.f_op = inode->i_op->default_file_ops; + if (file.f_op->open) + if (file.f_op->open(inode,&file)) + goto end_coredump; + if (!file.f_op->write) + goto close_coredump; + has_dumped = 1; + current->flags |= PF_DUMPCORE; + + DUMP_WRITE(&elf, sizeof(elf)); + offset += sizeof(elf); /* Elf header. */ + offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers. */ + + /* Set up the notes in similar form to SVR4 core dumps made + * with info from their /proc. + */ + memset(&psinfo, 0, sizeof(psinfo)); + memset(&prstatus, 0, sizeof(prstatus)); + + notes[0].name = "CORE"; + notes[0].type = NT_PRSTATUS; + notes[0].datasz = sizeof(prstatus); + notes[0].data = &prstatus; + prstatus.pr_info.si_signo = prstatus.pr_cursig = signr; + prstatus.pr_sigpend = current->signal; + prstatus.pr_sighold = current->blocked; + psinfo.pr_pid = prstatus.pr_pid = current->pid; + psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid; + psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; + psinfo.pr_sid = prstatus.pr_sid = current->session; + prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); + prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); + prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); + prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); + prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime); + prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime); + prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime); + prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime); + if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) { + printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) " + "(%d)\n", sizeof(elf_gregset_t), sizeof(struct pt_regs)); + } else { + *(struct pt_regs *)&prstatus.pr_reg = *regs; + } + + notes[1].name = "CORE"; + notes[1].type = NT_PRPSINFO; + notes[1].datasz = sizeof(psinfo); + notes[1].data = &psinfo; + psinfo.pr_state = current->state; + psinfo.pr_sname = + ((current->state < 0 || current->state > 5) ? + ('.') : ("RSDZTD"[current->state])); + psinfo.pr_zomb = psinfo.pr_sname == 'Z'; + psinfo.pr_nice = current->priority-15; + psinfo.pr_flag = current->flags; + psinfo.pr_uid = current->uid; + psinfo.pr_gid = current->gid; + { + int i, len; + + set_fs(fs); + + len = current->mm->arg_end - current->mm->arg_start; + len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len; + copy_from_user(&psinfo.pr_psargs, + (const char *)current->mm->arg_start, len); + for(i = 0; i < len; i++) + if (psinfo.pr_psargs[i] == 0) + psinfo.pr_psargs[i] = ' '; + psinfo.pr_psargs[len] = 0; + + set_fs(KERNEL_DS); + } + strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname)); + + notes[2].name = "CORE"; + notes[2].type = NT_TASKSTRUCT; + notes[2].datasz = sizeof(*current); + notes[2].data = current; + + /* Try to dump the fpu. */ + prstatus.pr_fpvalid = dump_fpu (&fpu); + if (!prstatus.pr_fpvalid) { + numnote--; + } else { + notes[3].name = "CORE"; + notes[3].type = NT_PRFPREG; + notes[3].datasz = sizeof(fpu); + notes[3].data = &fpu; + } + + /* Write notes phdr entry. */ + { + struct elf_phdr phdr; + int sz = 0; + + for(i = 0; i < numnote; i++) + sz += notesize(¬es[i]); + + phdr.p_type = PT_NOTE; + phdr.p_offset = offset; + phdr.p_vaddr = 0; + phdr.p_paddr = 0; + phdr.p_filesz = sz; + phdr.p_memsz = 0; + phdr.p_flags = 0; + phdr.p_align = 0; + + offset += phdr.p_filesz; + DUMP_WRITE(&phdr, sizeof(phdr)); + } + + /* Page-align dumped data. */ + dataoff = offset = roundup(offset, PAGE_SIZE); + + /* Write program headers for segments dump. */ + for(vma = current->mm->mmap, i = 0; + i < segs && vma != NULL; vma = vma->vm_next) { + struct elf_phdr phdr; + size_t sz; + + i++; + + sz = vma->vm_end - vma->vm_start; + + phdr.p_type = PT_LOAD; + phdr.p_offset = offset; + phdr.p_vaddr = vma->vm_start; + phdr.p_paddr = 0; + phdr.p_filesz = maydump(vma) ? sz : 0; + phdr.p_memsz = sz; + offset += phdr.p_filesz; + phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; + if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; + if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; + phdr.p_align = PAGE_SIZE; + + DUMP_WRITE(&phdr, sizeof(phdr)); + } + + for(i = 0; i < numnote; i++) + if (!writenote(¬es[i], &file)) + goto close_coredump; + + set_fs(fs); + + DUMP_SEEK(dataoff); + + for(i = 0, vma = current->mm->mmap; + i < segs && vma != NULL; + vma = vma->vm_next) { + unsigned long addr = vma->vm_start; + unsigned long len = vma->vm_end - vma->vm_start; + + if (!maydump(vma)) + continue; + i++; +#ifdef DEBUG + printk("elf_core_dump: writing %08lx %lx\n", addr, len); +#endif + DUMP_WRITE((void *)addr, len); + } + + if ((off_t) file.f_pos != offset) { + /* Sanity check. */ + printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n", + (off_t) file.f_pos, offset); + } + + close_coredump: + if (file.f_op->release) + file.f_op->release(inode,&file); + + end_coredump: + set_fs(fs); + iput(inode); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return has_dumped; +} + +__initfunc(int init_irix_binfmt(void)) +{ + return register_binfmt(&irix_format); +} + +#ifdef MODULE + +int init_module(void) +{ + /* Install the COFF, ELF and XOUT loaders. + * N.B. We *rely* on the table being the right size with the + * right number of free slots... + */ + return init_irix_binfmt(); +} + + +void cleanup_module( void) +{ + /* Remove the IRIX ELF loaders. */ + unregister_binfmt(&irix_format); +} +#endif diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.1.43/linux/arch/mips/kernel/irixioctl.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/irixioctl.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,257 @@ +/* $Id: irixioctl.c,v 1.1 1997/06/06 09:32:33 ralf Exp $ + * irixioctl.c: A fucking mess... + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#undef DEBUG_IOCTLS + +struct irix_termios { + tcflag_t c_iflag, c_oflag, c_cflag, c_lflag; + cc_t c_cc[NCCS]; +}; + +extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg); +extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count); +extern void start_tty(struct tty_struct *tty); + +static struct tty_struct *get_tty(int fd) +{ + struct file *filp; + + if(fd >= NR_OPEN || !(filp = current->files->fd[fd])) + return ((struct tty_struct *) 0); + if(filp->private_data) { + struct tty_struct *ttyp = (struct tty_struct *) filp->private_data; + + if(ttyp->magic == TTY_MAGIC) + return ttyp; + } + return ((struct tty_struct *) 0); +} + +static struct tty_struct *get_real_tty(struct tty_struct *tp) +{ + if(tp->driver.type == TTY_DRIVER_TYPE_PTY && + tp->driver.subtype == PTY_TYPE_MASTER) + return tp->link; + else + return tp; +} + +asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) +{ + struct tty_struct *tp, *rtp; + int error = 0; + int old_fs; + + lock_kernel(); +#ifdef DEBUG_IOCTLS + printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd); +#endif + switch(cmd) { + case 0x00005401: +#ifdef DEBUG_IOCTLS + printk("TCGETA, %08lx) ", arg); +#endif + error = sys_ioctl(fd, TCGETA, arg); + break; + + case 0x0000540d: { + struct termios kt; + struct irix_termios *it = (struct irix_termios *) arg; + +#ifdef DEBUG_IOCTLS + printk("TCGETS, %08lx) ", arg); +#endif + if(!access_ok(VERIFY_WRITE, it, sizeof(*it))) { + error = -EFAULT; + break; + } + old_fs = get_fs(); set_fs(get_ds()); + error = sys_ioctl(fd, TCGETS, (unsigned long) &kt); + set_fs(old_fs); + if(error) + break; + __put_user(kt.c_iflag, &it->c_iflag); + __put_user(kt.c_oflag, &it->c_oflag); + __put_user(kt.c_cflag, &it->c_cflag); + __put_user(kt.c_lflag, &it->c_lflag); + for(error = 0; error < NCCS; error++) + __put_user(kt.c_cc[error], &it->c_cc[error]); + error = 0; + break; + } + + case 0x0000540e: { + struct termios kt; + struct irix_termios *it = (struct irix_termios *) arg; + +#ifdef DEBUG_IOCTLS + printk("TCSETS, %08lx) ", arg); +#endif + if(!access_ok(VERIFY_READ, it, sizeof(*it))) { + error = -EFAULT; + break; + } + old_fs = get_fs(); set_fs(get_ds()); + error = sys_ioctl(fd, TCGETS, (unsigned long) &kt); + set_fs(old_fs); + if(error) + break; + __get_user(kt.c_iflag, &it->c_iflag); + __get_user(kt.c_oflag, &it->c_oflag); + __get_user(kt.c_cflag, &it->c_cflag); + __get_user(kt.c_lflag, &it->c_lflag); + for(error = 0; error < NCCS; error++) + __get_user(kt.c_cc[error], &it->c_cc[error]); + old_fs = get_fs(); set_fs(get_ds()); + error = sys_ioctl(fd, TCSETS, (unsigned long) &kt); + set_fs(old_fs); + break; + } + + case 0x0000540f: +#ifdef DEBUG_IOCTLS + printk("TCSETSW, %08lx) ", arg); +#endif + error = sys_ioctl(fd, TCSETSW, arg); + break; + + case 0x00005471: +#ifdef DEBUG_IOCTLS + printk("TIOCNOTTY, %08lx) ", arg); +#endif + error = sys_ioctl(fd, TIOCNOTTY, arg); + break; + + case 0x00007416: +#ifdef DEBUG_IOCTLS + printk("TIOCGSID, %08lx) ", arg); +#endif + tp = get_tty(fd); + if(!tp) { + error = -EINVAL; + break; + } + rtp = get_real_tty(tp); +#ifdef DEBUG_IOCTLS + printk("rtp->session=%d ", rtp->session); +#endif + error = put_user(rtp->session, (unsigned long *) arg); + break; + + case 0x746e: + /* TIOCSTART, same effect as hitting ^Q */ +#ifdef DEBUG_IOCTLS + printk("TIOCSTART, %08lx) ", arg); +#endif + tp = get_tty(fd); + if(!tp) { + error = -EINVAL; + break; + } + rtp = get_real_tty(tp); + start_tty(rtp); + break; + + case 0x20006968: +#ifdef DEBUG_IOCTLS + printk("SIOCGETLABEL, %08lx) ", arg); +#endif + error = -ENOPKG; + break; + + case 0x40047477: +#ifdef DEBUG_IOCTLS + printk("TIOCGPGRP, %08lx) ", arg); +#endif + error = sys_ioctl(fd, TIOCGPGRP, arg); +#ifdef DEBUG_IOCTLS + printk("arg=%d ", *(int *)arg); +#endif + break; + + case 0x40087468: +#ifdef DEBUG_IOCTLS + printk("TIOCGWINSZ, %08lx) ", arg); +#endif + error = sys_ioctl(fd, TIOCGWINSZ, arg); + break; + + case 0x8004667e: +#ifdef DEBUG_IOCTLS + printk("FIONBIO, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, FIONBIO, arg); + break; + + case 0x80047476: +#ifdef DEBUG_IOCTLS + printk("TIOCSPGRP, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, TIOCSPGRP, arg); + break; + + case 0x8020690c: +#ifdef DEBUG_IOCTLS + printk("SIOCSIFADDR, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, SIOCSIFADDR, arg); + break; + + case 0x80206910: +#ifdef DEBUG_IOCTLS + printk("SIOCSIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, SIOCSIFFLAGS, arg); + break; + + case 0xc0206911: +#ifdef DEBUG_IOCTLS + printk("SIOCGIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, SIOCGIFFLAGS, arg); + break; + + case 0xc020691b: +#ifdef DEBUG_IOCTLS + printk("SIOCGIFMETRIC, %08lx) arg=%d ", arg, *(int *)arg); +#endif + error = sys_ioctl(fd, SIOCGIFMETRIC, arg); + break; + + default: { + char *msg = "Unimplemented IOCTL cmd tell dm@engr.sgi.com\n"; + +#ifdef DEBUG_IOCTLS + printk("UNIMP_IOCTL, %08lx)\n", arg); +#endif + old_fs = get_fs(); set_fs(get_ds()); + sys_write(2, msg, strlen(msg)); + set_fs(old_fs); + printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n", + current->comm, current->pid, cmd); + do_exit(255); + } + + }; +#ifdef DEBUG_IOCTLS + printk("error=%d\n", error); +#endif + unlock_kernel(); + return error; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.1.43/linux/arch/mips/kernel/irixsig.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/irixsig.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,902 @@ +/* $Id: irixsig.c,v 1.2 1997/06/13 10:11:22 ralf Exp $ + * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef DEBUG_SIG + +#define _S(nr) (1<<((nr)-1)) + +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + +struct sigctx_irix5 { + u32 rmask, cp0_status; + u64 pc; + u64 regs[32]; + u64 fpregs[32]; + u32 usedfp, fpcsr, fpeir, sstk_flags; + u64 hi, lo; + u64 cp0_cause, cp0_badvaddr, _unused0; + u32 sigset[4]; + u64 weird_fpu_thing; + u64 _unused1[31]; +}; + +#ifdef DEBUG_SIG +/* Debugging */ +static inline void dump_irix5_sigctx(struct sigctx_irix5 *c) +{ + int i; + + printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n", + (unsigned long) c->rmask, + (unsigned long) c->cp0_status, + (unsigned long) c->pc); + printk("regs: "); + for(i = 0; i < 16; i++) + printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]); + printk("\nregs: "); + for(i = 16; i < 32; i++) + printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]); + printk("\nfpregs: "); + for(i = 0; i < 16; i++) + printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]); + printk("\nfpregs: "); + for(i = 16; i < 32; i++) + printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]); + printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n", + (int) c->usedfp, (unsigned long) c->fpcsr, + (unsigned long) c->fpeir, (unsigned long) c->sstk_flags); + printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n", + (unsigned long) c->hi, (unsigned long) c->lo, + (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr); + printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] " + "sigset<3>[%08lx]\n", (unsigned long) c->sigset[0], + (unsigned long) c->sigset[1], (unsigned long) c->sigset[2], + (unsigned long) c->sigset[3]); +} +#endif + +static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, + int signr, unsigned long oldmask) +{ + unsigned long sp; + struct sigctx_irix5 *ctx; + int i; + + sp = regs->regs[29]; + sp -= sizeof(struct sigctx_irix5); + sp &= ~(0xf); + ctx = (struct sigctx_irix5 *) sp; + if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx))) + goto segv_and_exit; + + __put_user(0, &ctx->weird_fpu_thing); + __put_user(~(0x00000001), &ctx->rmask); + __put_user(0, &ctx->regs[0]); + for(i = 1; i < 32; i++) + __put_user((u64) regs->regs[i], &ctx->regs[i]); + + __put_user((u64) regs->hi, &ctx->hi); + __put_user((u64) regs->lo, &ctx->lo); + __put_user((u64) regs->cp0_epc, &ctx->pc); + __put_user(current->used_math, &ctx->usedfp); + __put_user((u64) regs->cp0_cause, &ctx->cp0_cause); + __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr); + + __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */ + + __put_user(0, &ctx->sigset[1]); + __put_user(0, &ctx->sigset[2]); + __put_user(0, &ctx->sigset[3]); + __put_user(oldmask, &ctx->sigset[0]); + +#ifdef DEBUG_SIG + dump_irix5_sigctx(ctx); +#endif + + regs->regs[5] = 0; /* XXX sigcode XXX */ + regs->regs[4] = (unsigned long) signr; + regs->regs[6] = regs->regs[29] = sp; + regs->regs[7] = (unsigned long) sa->sa_handler; + regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline; + return; + +segv_and_exit: + lock_kernel(); + do_exit(SIGSEGV); + unlock_kernel(); +} + +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); + +asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) +{ + unsigned long mask = ~current->blocked; + unsigned long handler_signal = 0; + unsigned long signr; + struct sigaction * sa; + +#ifdef DEBUG_SIG + printk("[%s:%d] Delivering IRIX signal oldmask=%08lx\n", + current->comm, current->pid, oldmask); +#endif + while ((signr = current->signal & mask)) { + 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; + current->state = TASK_STOPPED; + notify_parent(current); + schedule(); + if (!(signr = current->exit_code)) + continue; + current->exit_code = 0; + if (signr == SIGSTOP) + continue; + if (_S(signr) & current->blocked) { + current->signal |= _S(signr); + continue; + } + sa = current->sig->action + signr - 1; + } + if (sa->sa_handler == SIG_IGN) { + if (signr != SIGCHLD) + continue; + /* check for SIGCHLD: it's special */ + while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + if (sa->sa_handler == SIG_DFL) { + if (current->pid == 1) + continue; + switch (signr) { + case SIGCONT: case SIGCHLD: case SIGWINCH: + continue; + + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + case SIGSTOP: + if (current->flags & PF_PTRACED) + continue; + current->state = TASK_STOPPED; + current->exit_code = signr; + 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 SIGBUS: + lock_kernel(); + if (current->binfmt && current->binfmt->core_dump) { + if (current->binfmt->core_dump(signr, regs)) + signr |= 0x80; + } + unlock_kernel(); + /* fall through */ + default: + current->signal |= _S(signr & 0x7f); + current->flags |= PF_SIGNALED; + lock_kernel(); /* 8-( */ + do_exit(signr); + unlock_kernel(); + } + } + /* + * OK, we're invoking a handler + */ + if (regs->orig_reg2 >= 0) { + if (regs->regs[2] == ERESTARTNOHAND) { + regs->regs[2] = EINTR; + } else if((regs->regs[2] == ERESTARTSYS && + !(sa->sa_flags & SA_RESTART))) { + regs->regs[2] = regs->orig_reg2; + regs->cp0_epc -= 8; + } + } + 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->regs[2] == ERESTARTNOHAND || + regs->regs[2] == ERESTARTSYS || + regs->regs[2] == ERESTARTNOINTR)) { + regs->regs[2] = regs->orig_reg2; + regs->cp0_epc -= 8; + } + if (!handler_signal) /* no handler will be called - return 0 */ + return 0; + signr = 1; + sa = current->sig->action; + for (mask = 1 ; mask ; sa++,signr++,mask += mask) { + if (mask > handler_signal) + break; + if (!(mask & handler_signal)) + continue; + setup_irix_frame(sa, regs, signr, oldmask); + if (sa->sa_flags & SA_ONESHOT) + sa->sa_handler = NULL; + current->blocked |= sa->sa_mask; + oldmask |= sa->sa_mask; + } + + return 1; +} + +asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) +{ + struct sigctx_irix5 *context, *magic; + unsigned long umask, mask; + u64 *fregs, res; + int sig, i, base = 0; + + if(regs->regs[2] == 1000) + base = 1; + + context = (struct sigctx_irix5 *) regs->regs[base + 4]; + magic = (struct sigctx_irix5 *) regs->regs[base + 5]; + sig = (int) regs->regs[base + 6]; +#ifdef DEBUG_SIG + printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n", + current->comm, current->pid, context, magic, sig); +#endif + if (!context) + context = magic; + if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5))) + goto badframe; + +#ifdef DEBUG_SIG + dump_irix5_sigctx(context); +#endif + + __get_user(regs->cp0_epc, &context->pc); + umask = context->rmask; mask = 2; + for (i = 1; i < 32; i++, mask <<= 1) { + if(umask & mask) + __get_user(regs->regs[i], &context->regs[i]); + } + __get_user(regs->hi, &context->hi); + __get_user(regs->lo, &context->lo); + + if ((umask & 1) && context->usedfp) { + fregs = (u64 *) ¤t->tss.fpu; + for(i = 0; i < 32; i++) + fregs[i] = (u64) context->fpregs[i]; + __get_user(current->tss.fpu.hard.control, &context->fpcsr); + } + + /* XXX do sigstack crapola here... XXX */ + + regs->orig_reg2 = -1; + __get_user(current->blocked, &context->sigset[0]); + current->blocked &= _BLOCKABLE; + __get_user(res, &context->regs[2]); + return res; + +badframe: + lock_kernel(); + do_exit(SIGSEGV); + unlock_kernel(); + + return res; +} + +struct sigact_irix5 { + int flags; + void (*handler)(int); + u32 sigset[4]; + int _unused0[2]; +}; + +#ifdef DEBUG_SIG +static inline void dump_sigact_irix5(struct sigact_irix5 *p) +{ + printk("", p->flags, + (unsigned long) p->handler, + (unsigned long) p->sigset[0]); +} +#endif + +static inline void check_pending(int signum) +{ + struct sigaction *p; + + p = signum - 1 + current->sig->action; + spin_lock(¤t->sigmask_lock); + if (p->sa_handler == SIG_IGN) { + current->signal &= ~_S(signum); + } else if (p->sa_handler == SIG_DFL) { + if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH) + return; + current->signal &= ~_S(signum); + } + spin_unlock(¤t->sigmask_lock); +} + +asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, + struct sigact_irix5 *old, unsigned long trampoline) +{ + struct sigaction new_sa, *p; + int res; + +#ifdef DEBUG_SIG + printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"), + (!old ? "0" : "OLD"), trampoline); + if(new) { + dump_sigact_irix5(new); printk(" "); + } +#endif + if(sig < 1 || sig > 32) { + return -EINVAL; + } + p = sig - 1 + current->sig->action; + + if(new) { + res = verify_area(VERIFY_READ, new, sizeof(*new)); + if(res) + return res; + if(sig == SIGKILL || sig == SIGSTOP) { + return -EINVAL; + } + __get_user(new_sa.sa_flags, &new->flags); + __get_user(new_sa.sa_handler, &(__sighandler_t) new->handler); + __get_user(new_sa.sa_mask, &new->sigset[0]); + + if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { + res = verify_area(VERIFY_READ, new_sa.sa_handler, 1); + if(res) + return res; + } + } + /* Hmmm... methinks IRIX libc always passes a valid trampoline + * value for all invocations of sigaction. Will have to + * investigate. POSIX POSIX, die die die... + */ + current->tss.irix_trampoline = trampoline; + if(old) { + int res = verify_area(VERIFY_WRITE, old, sizeof(*old)); + if(res) + return res; + __put_user(p->sa_flags, &old->flags); + __put_user(p->sa_handler, &old->handler); + __put_user(p->sa_mask, &old->sigset[0]); + __put_user(0, &old->sigset[1]); + __put_user(0, &old->sigset[2]); + __put_user(0, &old->sigset[3]); + __put_user(0, &old->_unused0[0]); + __put_user(0, &old->_unused0[1]); + } + if(new) { + spin_lock_irq(¤t->sig->siglock); + *p = new_sa; + check_pending(sig); + spin_unlock_irq(¤t->sig->siglock); + } + + return 0; +} + +asmlinkage int irix_sigpending(unsigned long *set) +{ + int res; + + lock_kernel(); + res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4)); + if(!res) { + /* fill in "set" with signals pending but blocked. */ + spin_lock_irq(¤t->sigmask_lock); + __put_user(0, &set[1]); + __put_user(0, &set[2]); + __put_user(0, &set[3]); + __put_user((current->blocked & current->signal), &set[0]); + spin_unlock_irq(¤t->sigmask_lock); + } + return res; +} + +asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) +{ + unsigned long bits, oldbits = current->blocked; + int error; + + if(new) { + error = verify_area(VERIFY_READ, new, (sizeof(unsigned long) * 4)); + if(error) + return error; + bits = new[0] & _BLOCKABLE; + switch(how) { + case 1: + current->blocked |= bits; + break; + + case 2: + current->blocked &= ~bits; + break; + + case 3: + case 256: + current->blocked = bits; + break; + + default: + return -EINVAL; + } + } + if(old) { + error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4)); + if(error) + return error; + __put_user(0, &old[1]); + __put_user(0, &old[2]); + __put_user(0, &old[3]); + __put_user(oldbits, &old[0]); + } + + return 0; +} + +asmlinkage int irix_sigsuspend(struct pt_regs *regs) +{ + unsigned int mask; + unsigned long *uset; + int base = 0, error; + + if(regs->regs[2] == 1000) + base = 1; + + uset = (unsigned long *) regs->regs[base + 4]; + if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4))) + return -EFAULT; + mask = current->blocked; + + current->blocked = uset[0] & _BLOCKABLE; + while(1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if(do_irix_signal(mask, regs)) + return -EINTR; + } + return error; +} + +/* hate hate hate... */ +struct irix5_siginfo { + int sig, code, error; + union { + char unused[128 - (3 * 4)]; /* Safety net. */ + struct { + int pid; + union { + int uid; + struct { + int utime, status, stime; + } child; + } procdata; + } procinfo; + + unsigned long fault_addr; + + struct { + int fd; + long band; + } fileinfo; + + unsigned long sigval; + } stuff; +}; + +static inline unsigned long timespectojiffies(struct timespec *value) +{ + unsigned long sec = (unsigned) value->tv_sec; + long nsec = value->tv_nsec; + + if (sec > (LONG_MAX / HZ)) + return LONG_MAX; + nsec += 1000000000L / HZ - 1; + nsec /= 1000000000L / HZ; + return HZ * sec + nsec; +} + +asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, + struct timespec *tp) +{ + unsigned long mask, kset, expire = 0; + int sig, error, timeo = 0; + + lock_kernel(); +#ifdef DEBUG_SIG + printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n", + current->comm, current->pid, set, info, tp); +#endif + + /* Must always specify the signal set. */ + if(!set) + return -EINVAL; + + error = get_user(kset, &set[0]); + if(error) + goto out; + + if(info && clear_user(info, sizeof(*info))) { + error = -EFAULT; + goto out; + } + + if(tp) { + error = verify_area(VERIFY_READ, tp, sizeof(*tp)); + if(error) + return error; + if(!tp->tv_sec && !tp->tv_nsec) { + error = -EINVAL; + goto out; + } + expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec)+jiffies; + current->timeout = expire; + } + + while(1) { + current->state = TASK_INTERRUPTIBLE; schedule(); + if(current->signal & kset) break; + if(tp && expire <= jiffies) { + timeo = 1; + break; + } + if(current->signal & ~(current->blocked)) return -EINTR; + } + + if(timeo) return -EAGAIN; + for(sig = 1, mask = 2; mask; mask <<= 1, sig++) { + if(!(mask & kset)) continue; + if(mask & current->signal) { + /* XXX need more than this... */ + if(info) info->sig = sig; + error = 0; + goto out; + } + } + + /* Should not get here, but do something sane if we do. */ + error = -EINTR; + +out: + unlock_kernel(); + return error; +} + +/* This is here because of irix5_siginfo definition. */ +#define P_PID 0 +#define P_PGID 2 +#define P_ALL 7 + +extern int getrusage(struct task_struct *, int, struct rusage *); +extern void release(struct task_struct * p); + +#define W_EXITED 1 +#define W_TRAPPED 2 +#define W_STOPPED 4 +#define W_CONT 8 +#define W_NOHANG 64 + +#define W_MASK (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG) + +asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info, + int options, struct rusage *ru) +{ + int flag, retval; + struct wait_queue wait = { current, NULL }; + struct task_struct *p; + + lock_kernel(); + if(!info) { + retval = -EINVAL; + goto out; + } + retval = verify_area(VERIFY_WRITE, info, sizeof(*info)); + if(retval) + goto out; + if(ru) { + retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru)); + if(retval) + goto out; + } + if(options & ~(W_MASK)) { + retval = -EINVAL; + goto out; + } + if(type != P_PID && type != P_PGID && type != P_ALL) { + retval = -EINVAL; + goto out; + } + add_wait_queue(¤t->wait_chldexit, &wait); +repeat: + flag = 0; + for(p = current->p_cptr; p; p = p->p_osptr) { + if((type == P_PID) && p->pid != pid) + continue; + if((type == P_PGID) && p->pgrp != pid) + continue; + if((p->exit_signal != SIGCHLD)) + continue; + flag = 1; + switch(p->state) { + case TASK_STOPPED: + if (!p->exit_code) + continue; + if (!(options & (W_TRAPPED|W_STOPPED)) && + !(p->flags & PF_PTRACED)) + continue; + if (ru != NULL) + getrusage(p, RUSAGE_BOTH, ru); + __put_user(SIGCHLD, &info->sig); + __put_user(0, &info->code); + __put_user(p->pid, &info->stuff.procinfo.pid); + __put_user((p->exit_code >> 8) & 0xff, + &info->stuff.procinfo.procdata.child.status); + __put_user(p->times.tms_utime, &info->stuff.procinfo.procdata.child.utime); + __put_user(p->times.tms_stime, &info->stuff.procinfo.procdata.child.stime); + p->exit_code = 0; + retval = 0; + goto end_waitsys; + case TASK_ZOMBIE: + current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; + current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; + if (ru != NULL) + getrusage(p, RUSAGE_BOTH, ru); + __put_user(SIGCHLD, &info->sig); + __put_user(1, &info->code); /* CLD_EXITED */ + __put_user(p->pid, &info->stuff.procinfo.pid); + __put_user((p->exit_code >> 8) & 0xff, + &info->stuff.procinfo.procdata.child.status); + __put_user(p->times.tms_utime, + &info->stuff.procinfo.procdata.child.utime); + __put_user(p->times.tms_stime, + &info->stuff.procinfo.procdata.child.stime); + retval = 0; + if (p->p_opptr != p->p_pptr) { + REMOVE_LINKS(p); + p->p_pptr = p->p_opptr; + SET_LINKS(p); + notify_parent(p); + } else + release(p); + goto end_waitsys; + default: + continue; + } + } + if(flag) { + retval = 0; + if(options & W_NOHANG) + goto end_waitsys; + retval = -ERESTARTSYS; + if(current->signal & ~current->blocked) + goto end_waitsys; + current->state = TASK_INTERRUPTIBLE; + schedule(); + goto repeat; + } + retval = -ECHILD; +end_waitsys: + remove_wait_queue(¤t->wait_chldexit, &wait); + +out: + unlock_kernel(); + return retval; +} + +struct irix5_context { + u32 flags; + u32 link; + u32 sigmask[4]; + struct { u32 sp, size, flags; } stack; + int regs[36]; + u32 fpregs[32]; + u32 fpcsr; + u32 _unused0; + u32 _unused1[47]; + u32 weird_graphics_thing; +}; + +asmlinkage int irix_getcontext(struct pt_regs *regs) +{ + int error, i, base = 0; + struct irix5_context *ctx; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + ctx = (struct irix5_context *) regs->regs[base + 4]; + +#ifdef DEBUG_SIG + printk("[%s:%d] irix_getcontext(%p)\n", + current->comm, current->pid, ctx); +#endif + + error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx)); + if(error) + goto out; + ctx->flags = 0x0f; + ctx->link = current->tss.irix_oldctx; + ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0; + ctx->sigmask[0] = current->blocked; + + /* XXX Do sigstack stuff someday... */ + ctx->stack.sp = ctx->stack.size = ctx->stack.flags = 0; + + ctx->weird_graphics_thing = 0; + ctx->regs[0] = 0; + for(i = 1; i < 32; i++) + ctx->regs[i] = regs->regs[i]; + ctx->regs[32] = regs->lo; + ctx->regs[33] = regs->hi; + ctx->regs[34] = regs->cp0_cause; + ctx->regs[35] = regs->cp0_epc; + if(!current->used_math) { + ctx->flags &= ~(0x08); + } else { + /* XXX wheee... */ + printk("Wheee, no code for saving IRIX FPU context yet.\n"); + } + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) +{ + int error, base = 0; + struct irix5_context *ctx; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + ctx = (struct irix5_context *) regs->regs[base + 4]; + +#ifdef DEBUG_SIG + printk("[%s:%d] irix_setcontext(%p)\n", + current->comm, current->pid, ctx); +#endif + + error = verify_area(VERIFY_READ, ctx, sizeof(*ctx)); + if(error) + goto out; + + if(ctx->flags & 0x02) { + /* XXX sigstack garbage, todo... */ + printk("Wheee, cannot do sigstack stuff in setcontext\n"); + } + + if(ctx->flags & 0x04) { + int i; + + /* XXX extra control block stuff... todo... */ + for(i = 1; i < 32; i++) + regs->regs[i] = ctx->regs[i]; + regs->lo = ctx->regs[32]; + regs->hi = ctx->regs[33]; + regs->cp0_epc = ctx->regs[35]; + } + + if(ctx->flags & 0x08) { + /* XXX fpu context, blah... */ + printk("Wheee, cannot restore FPU context yet...\n"); + } + current->tss.irix_oldctx = ctx->link; + error = regs->regs[2]; + +out: + unlock_kernel(); + return error; +} + +struct irix_sigstack { unsigned long sp; int status; }; + +asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_SIG + printk("[%s:%d] irix_sigstack(%p,%p)\n", + current->comm, current->pid, new, old); +#endif + if(new) { + error = verify_area(VERIFY_READ, new, sizeof(*new)); + if(error) + goto out; + } + + if(old) { + error = verify_area(VERIFY_WRITE, old, sizeof(*old)); + if(error) + goto out; + } + error = 0; +out: + unlock_kernel(); + return error; +} + +struct irix_sigaltstack { unsigned long sp; int size; int status; }; + +asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new, + struct irix_sigaltstack *old) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_SIG + printk("[%s:%d] irix_sigaltstack(%p,%p)\n", + current->comm, current->pid, new, old); +#endif + if(new) { + error = verify_area(VERIFY_READ, new, sizeof(*new)); + if(error) + goto out; + } + + if(old) { + error = verify_area(VERIFY_WRITE, old, sizeof(*old)); + if(error) + goto out; + } + error = 0; + +out: + error = 0; + unlock_kernel(); + + return error; +} + +struct irix_procset { + int cmd, ltype, lid, rtype, rid; +}; + +asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig) +{ + int error; + + lock_kernel(); + error = verify_area(VERIFY_READ, pset, sizeof(*pset)); + if(error) + goto out; +#ifdef DEBUG_SIG + printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n", + current->comm, current->pid, + pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid, + sig); +#endif + + error = -EINVAL; + +out: + unlock_kernel(); + return error; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.1.43/linux/arch/mips/kernel/irq.c Mon Apr 14 16:28:06 1997 +++ linux/arch/mips/kernel/irq.c Thu Jun 26 12:33:37 1997 @@ -8,29 +8,18 @@ * instead of just grabbing them. Thus setups with different IRQ numbers * shouldn't result in any weird surprises, and installing new handlers * should be easier. - */ - -/* - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -/* - * 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 - * machines. + * Mips support by Ralf Baechle and Andreas Busse */ - -#include +#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -42,51 +31,65 @@ #include #include #include - -#define TIMER_IRQ 0 /* Keep this in sync with time.c */ +#include +#ifdef CONFIG_SGI +#include +#endif unsigned char cache_21 = 0xff; unsigned char cache_A1 = 0xff; +unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; -void disable_irq(unsigned int irq_nr) +/* + * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and + * PCI devices. Other onboard hardware needs specific routines. + */ +static inline void mask_irq(unsigned int irq_nr) { - unsigned long flags; unsigned char mask; mask = 1 << (irq_nr & 7); - save_flags(flags); if (irq_nr < 8) { - cli(); cache_21 |= mask; outb(cache_21,0x21); - restore_flags(flags); - return; + } else { + cache_A1 |= mask; + outb(cache_A1,0xA1); } - cli(); - cache_A1 |= mask; - outb(cache_A1,0xA1); - restore_flags(flags); } -void enable_irq(unsigned int irq_nr) +static inline void unmask_irq(unsigned int irq_nr) { - unsigned long flags; unsigned char mask; mask = ~(1 << (irq_nr & 7)); - save_flags(flags); if (irq_nr < 8) { - cli(); cache_21 &= mask; outb(cache_21,0x21); - restore_flags(flags); - return; + } else { + cache_A1 &= mask; + outb(cache_A1,0xA1); } +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_flags(flags); + cli(); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + save_flags(flags); cli(); - cache_A1 &= mask; - outb(cache_A1,0xA1); + unmask_irq(irq_nr); restore_flags(flags); } @@ -98,16 +101,11 @@ extern void fast_interrupt(void); extern void bad_interrupt(void); -/* - * Initial irq handlers. - */ -static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL}; -static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL}; -static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL}; - -static struct irqaction *irq_action[16] = { - NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL +static struct irqaction *irq_action[32] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int get_irq_list(char *buf) @@ -115,10 +113,10 @@ int i, len = 0; struct irqaction * action; - for (i = 0 ; i < 16 ; i++) { - action = *(i + irq_action); + for (i = 0 ; i < 32 ; i++) { + action = irq_action[i]; if (!action) - continue; + continue; len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat.interrupts[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -133,6 +131,15 @@ return len; } +atomic_t __mips_bh_counter; + +#ifdef __SMP__ +#error Send superfluous SMP boxes to ralf@uni-koblenz.de +#else +#define irq_enter(cpu, irq) (++local_irq_count[cpu]) +#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#endif + /* * do_IRQ handles IRQ's that have been installed without the * SA_INTERRUPT flag: it uses the full signal-handling return @@ -143,14 +150,23 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { struct irqaction * action = *(irq + irq_action); + int do_random, cpu = smp_processor_id(); + irq_enter(cpu, irq); kstat.interrupts[irq]++; - if (action->flags & SA_SAMPLE_RANDOM) + + /* slow interrupts run with interrupts enabled */ + sti(); + action = *(irq + irq_action); + do_random = 0; + while (action) { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } + if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - while (action) { - action->handler(irq, action->dev_id, regs); - action = action->next; - } + irq_exit(cpu, irq); } /* @@ -160,18 +176,70 @@ */ asmlinkage void do_fast_IRQ(int irq) { - struct irqaction * action = *(irq + irq_action); + struct irqaction * action; + int do_random, cpu = smp_processor_id(); + irq_enter(cpu, irq); kstat.interrupts[irq]++; - if (action->flags & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + action = *(irq + irq_action); + do_random = 0; while (action) { - action->handler(irq, action->dev_id, NULL); - action = action->next; + do_random |= action->flags; + action->handler(irq, action->dev_id, NULL); + action = action->next; } + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + irq_exit(cpu, irq); } -#define SA_PROBE SA_ONESHOT +/* + * Used only for setup of PC style interrupts and therefore still + * called setup_x86_irq. Later on I'll provide a machine specific + * function with similar purpose. Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_x86_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_flags(flags); + cli(); + *p = new; + + if (!shared) { + if (new->flags & SA_INTERRUPT) + set_int_vector(irq,fast_interrupt); + else + set_int_vector(irq,interrupt); + unmask_irq(irq); + } + restore_flags(flags); + return 0; +} int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -179,42 +247,17 @@ const char * devname, void *dev_id) { - struct irqaction * action, *tmp = NULL; - unsigned long flags; + int retval; + struct irqaction * action; - if (irq > 15) + if (irq > 31) return -EINVAL; if (!handler) - return -EINVAL; - action = *(irq + irq_action); - if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { - for (tmp = action; tmp->next; tmp = tmp->next); - } else { - return -EBUSY; - } - if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { - printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); - return -EBUSY; - } - } - if (irqflags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - save_flags(flags); - cli(); - if (irq == 2) - action = &cascade_irq; - else if (irq == 13) - action = &math_irq; - else if (irq == TIMER_IRQ) - action = &timer_irq; - else - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - - if (!action) { - restore_flags(flags); - return -ENOMEM; - } + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; action->handler = handler; action->flags = irqflags; @@ -223,116 +266,61 @@ action->next = NULL; action->dev_id = dev_id; - if (tmp) { - tmp->next = action; - } else { - *(irq + irq_action) = action; - if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */ - /* - * FIXME: Does the SA_INTERRUPT flag make any sense on MIPS??? - */ - if (action->flags & SA_INTERRUPT) - set_int_vector(irq,fast_interrupt); - else - set_int_vector(irq,interrupt); - } - if (irq < 8) { - cache_21 &= ~(1< 15) { + if (irq > 31) { printk("Trying to free IRQ%d\n",irq); return; } - if (!action->handler) { - printk("Trying to free free IRQ%d\n",irq); - return; - } - if (dev_id) { - for (; action; action = action->next) { - if (action->dev_id == dev_id) break; - tmp = action; - } - if (!action) { - printk("Trying to free free shared IRQ%d\n",irq); - return; - } - } else if (action->flags & SA_SHIRQ) { - printk("Trying to free shared IRQ%d with NULL device ID\n", irq); - return; - } - save_flags(flags); - cli(); - if (action && tmp) { - tmp->next = action->next; - } else { - *(irq + irq_action) = action->next; - } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; - if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ)) - memset(action, 0, sizeof(struct irqaction)); - else - kfree_s(action, sizeof(struct irqaction)); - - if (!(*(irq + irq_action))) { - if (irq < 8) { - cache_21 |= 1 << irq; - outb(cache_21,0x21); - } else { - cache_A1 |= 1 << (irq-8); - outb(cache_A1,0xA1); - } - set_int_vector(irq,bad_interrupt); + /* Found it - now free it */ + save_flags(flags); + cli(); + *p = action->next; + if (!irq[irq_action]) { + mask_irq(irq); + set_int_vector(irq, bad_interrupt); + } + restore_flags(flags); + kfree(action); + return; } - restore_flags(flags); + printk("Trying to free free IRQ%d\n",irq); } -static void no_action(int cpl, void *dev_id, struct pt_regs * regs) { } - unsigned long probe_irq_on (void) { unsigned int i, irqs = 0, irqmask; unsigned long delay; - /* first, snaffle up any unassigned irqs */ + /* first, enable any unassigned (E)ISA irqs */ for (i = 15; i > 0; i--) { - if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) { + if (!irq_action[i]) { enable_irq(i); irqs |= (1 << i); } } /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */ + for (delay = jiffies + HZ/10; delay > jiffies; ) + /* about 100ms delay */; /* now filter out any obviously spurious interrupts */ irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i) & irqmask) { - irqs ^= (1 << i); - free_irq(i, NULL); - } - } -#ifdef DEBUG - printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - return irqs; + return irqs & ~irqmask; } int probe_irq_off (unsigned long irqs) @@ -340,11 +328,6 @@ unsigned int i, irqmask; irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i)) { - free_irq(i, NULL); - } - } #ifdef DEBUG printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); #endif @@ -357,45 +340,11 @@ return i; } -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { int i; - 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", NULL)) - printk("Unable to get IRQ2 for cascade\n"); - break; - default: - panic("Unknown machtype in init_IRQ"); - } - - for (i = 0; i < 16 ; i++) + for (i = 0; i < 32 ; i++) set_int_vector(i, bad_interrupt); - - /* initialize the bottom half routines. */ - for (i = 0; i < 32; i++) { - bh_base[i].routine = NULL; - bh_base[i].data = NULL; - } - bh_active = 0; - atomic_set(&intr_count, 0); + irq_setup(); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/jazz-c.c linux/arch/mips/kernel/jazz-c.c --- v2.1.43/linux/arch/mips/kernel/jazz-c.c Wed Dec 13 02:39:43 1995 +++ linux/arch/mips/kernel/jazz-c.c Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -/* - * 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 v2.1.43/linux/arch/mips/kernel/jazzdma.c linux/arch/mips/kernel/jazzdma.c --- v2.1.43/linux/arch/mips/kernel/jazzdma.c Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/kernel/jazzdma.c Wed Dec 31 16:00:00 1969 @@ -1,513 +0,0 @@ -/* - * jazzdma.c - * - * Mips Jazz DMA controller support - * (C) 1995 Andreas Busse - * - * NOTE: Some of the argument checking 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 v2.1.43/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.1.43/linux/arch/mips/kernel/mips_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/mips_ksyms.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,44 @@ +/* + * Export MIPS-specific functions needed for loadable modules. + * + * 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) 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EXPORT_SYMBOL(EISA_bus); + +/* + * String functions + */ +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(bcopy); + +EXPORT_SYMBOL(__mips_bh_counter); +EXPORT_SYMBOL(local_irq_count); + +/* Networking helper routines. */ +EXPORT_SYMBOL(csum_partial_copy); + +/* + * Functions to control caches. + */ +EXPORT_SYMBOL(fd_cacheflush); + +/* + * Base address of ports for Intel style I/O. + */ +EXPORT_SYMBOL(port_base); diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c --- v2.1.43/linux/arch/mips/kernel/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/pci.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,180 @@ +/* + * 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. + * + * MIPS implementation of PCI BIOS services for PCI support. + */ +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PCI + +/* + * BIOS32 replacement. + */ +__initfunc(unsigned long pcibios_init(unsigned long memory_start, + unsigned long memory_end)) +{ + return memory_start; +} + +#else /* defined(CONFIG_PCI) */ + +/* + * Following the generic parts of the MIPS BIOS32 code. + */ + +int pcibios_present (void) +{ + return _pcibios_init != NULL; +} + +/* + * Given the vendor and device ids, find the n'th instance of that device + * in the system. + */ +int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, + unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->vendor == vendor && dev->device == device_id) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +/* + * Given the class, find the n'th instance of that device + * in the system. + */ +int pcibios_find_class (unsigned int class_code, unsigned short index, + unsigned char *bus, unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->class == class_code) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +const char *pcibios_strerror (int error) +{ + static char buf[80]; + + switch (error) { + case PCIBIOS_SUCCESSFUL: + return "SUCCESSFUL"; + + case PCIBIOS_FUNC_NOT_SUPPORTED: + return "FUNC_NOT_SUPPORTED"; + + case PCIBIOS_BAD_VENDOR_ID: + return "SUCCESSFUL"; + + case PCIBIOS_DEVICE_NOT_FOUND: + return "DEVICE_NOT_FOUND"; + + case PCIBIOS_BAD_REGISTER_NUMBER: + return "BAD_REGISTER_NUMBER"; + + default: + sprintf (buf, "UNKNOWN RETURN 0x%x", error); + return buf; + } +} + +/* + * The functions below are machine specific and must be reimplented for + * each PCI chipset configuration. We just run the hook to the machine + * specific implementation. + */ +unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end); +__initfunc(unsigned long pcibios_init(unsigned long memory_start, + unsigned long memory_end)) +{ + return _pcibios_init ? _pcibios_init(memory_start, memory_end) + : memory_start; +} + +unsigned long (*_pcibios_fixup) (unsigned long memory_start, + unsigned long memory_end); +unsigned long pcibios_fixup (unsigned long memory_start, + unsigned long memory_end) +{ + return _pcibios_fixup(memory_start, memory_end); +} + +int (*_pcibios_read_config_byte) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val); +int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val) +{ + return _pcibios_read_config_byte(bus, dev_fn, where, val); +} + +int (*_pcibios_read_config_word) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val); +int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val) +{ + return _pcibios_read_config_word(bus, dev_fn, where, val); +} + +int (*_pcibios_read_config_dword) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val); +int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val) +{ + return _pcibios_read_config_dword(bus, dev_fn, where, val); +} + +int (*_pcibios_write_config_byte) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val); +int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val) +{ + return _pcibios_write_config_byte(bus, dev_fn, where, val); +} + +int (*_pcibios_write_config_word) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val); +int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val) +{ + return _pcibios_write_config_word(bus, dev_fn, where, val); +} + +int (*_pcibios_write_config_dword) (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val); +int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val) +{ + return _pcibios_write_config_dword(bus, dev_fn, where, val); +} + +#endif /* defined(CONFIG_PCI) */ diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/pica.S linux/arch/mips/kernel/pica.S --- v2.1.43/linux/arch/mips/kernel/pica.S Wed Dec 13 02:39:43 1995 +++ linux/arch/mips/kernel/pica.S Wed Dec 31 16:00:00 1969 @@ -1,268 +0,0 @@ -/* - * 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 v2.1.43/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c --- v2.1.43/linux/arch/mips/kernel/proc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/proc.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,62 @@ +/* + * linux/arch/mips/kernel/proc.c + * + * Copyright (C) 1995, 1996 Ralf Baechle + */ +#include +#include +#include +#include + +unsigned long dflushes = 0; +unsigned long iflushes = 0; +unsigned long unaligned_instructions; + +/* + * BUFFER is PAGE_SIZE bytes long. + * + * Currently /proc/cpuinfo is being abused to print data about the + * number of date/instruction cacheflushes. + */ +int get_cpuinfo(char *buffer) +{ + const char *cpu_name[] = CPU_NAMES; + const char *mach_group_names[] = GROUP_NAMES; + const char *mach_unknown_names[] = GROUP_UNKNOWN_NAMES; + const char *mach_jazz_names[] = GROUP_JAZZ_NAMES; + const char *mach_dec_names[] = GROUP_DEC_NAMES; + const char *mach_arc_names[] = GROUP_ARC_NAMES; + const char *mach_sni_rm_names[] = GROUP_SNI_RM_NAMES; + const char **mach_group_to_name[] = { mach_unknown_names, mach_jazz_names, + mach_dec_names, mach_arc_names, mach_sni_rm_names}; + unsigned int version = read_32bit_cp0_register(CP0_PRID); + int len; + + len = sprintf(buffer, "cpu\t\t\t: MIPS\n"); + len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", + cpu_name[mips_cputype <= CPU_LAST ? + mips_cputype : + CPU_UNKNOWN], + (version >> 4) & 0x0f, + version & 0x0f); + len += sprintf(buffer + len, "system type\t\t: %s %s\n", + mach_group_names[mips_machgroup], + mach_group_to_name[mips_machgroup][mips_machtype]); + len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", + (loops_per_sec + 2500) / 500000, + ((loops_per_sec + 2500) / 5000) % 100); +#if defined (__MIPSEB__) + len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); +#endif +#if defined (__MIPSEL__) + len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); +#endif + len += sprintf(buffer + len, "D-cache flushes\t\t: %lu\n", + dflushes); + len += sprintf(buffer + len, "I-cache flushes\t\t: %lu\n", + iflushes); + len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", + unaligned_instructions); + + return len; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.1.43/linux/arch/mips/kernel/process.c Tue May 13 22:41:02 1997 +++ linux/arch/mips/kernel/process.c Thu Jun 26 12:33:37 1997 @@ -2,10 +2,14 @@ * linux/arch/mips/kernel/process.c * * Copyright (C) 1995 Ralf Baechle - * written by Ralf Baechle * - * This file handles the architecture-dependent parts of initialization + * Modified for R3000/DECStation support by Paul M. Antoine 1995, 1996 + * + * This file handles the architecture-dependent parts of initialization, + * though it does not yet currently fully support the DECStation, + * or R3000 - PMA. */ +#include #include #include #include @@ -14,144 +18,83 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include #include #include +#include #include +#include +#ifdef CONFIG_SGI +#include +#endif -/* - * Initial task structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; -unsigned long init_user_stack[1024] = { STACK_MAGIC, }; -static struct vm_area_struct init_mmap = INIT_MMAP; -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; - -struct mm_struct init_mm = INIT_MM; -struct task_struct init_task = INIT_TASK; +int active_ds = USER_DS; asmlinkage void ret_from_sys_call(void); /* - * 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... + * Do necessary setup to start up a newly executed thread. */ -static inline void kb_wait(void) -{ - int i; - - for (i=0; i<0x10000; i++) - if ((inb_p(0x64) & 0x02) == 0) - break; -} - -/* - * Hard reset for Deskstation Tyne - * No hint how this works on Pica boards. - */ -void hard_reset_now(void) -{ - int i, j; - - sti(); - for (;;) { - for (i=0; i<100; i++) { - kb_wait(); - for(j = 0; j < 100000 ; j++) - /* nothing */; - outb(0xfe,0x64); /* pulse reset low */ - } - } -} - -void show_regs(struct pt_regs * regs) +void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { - /* - * 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); + /* New thread looses kernel privileges. */ + regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER; + regs->cp0_epc = pc; + regs->regs[29] = sp; + current->tss.current_ds = USER_DS; } -/* - * Free current thread data structures etc.. - */ void exit_thread(void) { - /* - * Nothing to do - */ } void flush_thread(void) { - /* - * Nothing to do - */ } void release_thread(struct task_struct *dead_task) { - /* - * Nothing to do - */ } - + int 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; + long childksp; - childksp = p->kernel_stack_page + PAGE_SIZE - 8; - /* - * set up new TSS - */ - childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1; + childksp = (unsigned long)p + KERNEL_STACK_SIZE - 8; + + /* set up new TSS. */ + childregs = ((struct pt_regs *) ((unsigned long)p + KERNEL_STACK_SIZE)) - 1; *childregs = *regs; - 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; + childregs->regs[7] = 0; /* Clear error flag */ + if(current->personality == PER_LINUX) { + childregs->regs[2] = 0; /* Child gets zero as return value */ + regs->regs[2] = p->pid; + } else { + /* Under IRIX things are a little different. */ + childregs->regs[2] = 0; + childregs->regs[3] = 1; + regs->regs[2] = p->pid; + regs->regs[3] = 0; + } + if (childregs->cp0_status & ST0_CU0) { + childregs->regs[29] = childksp; + p->tss.current_ds = KERNEL_DS; + } else { + childregs->regs[29] = usp; + p->tss.current_ds = USER_DS; + } p->tss.ksp = childksp; - p->tss.reg29 = (unsigned long) childregs; /* new sp */ + p->tss.reg29 = (unsigned long) childregs; p->tss.reg31 = (unsigned long) ret_from_sys_call; /* @@ -161,31 +104,35 @@ 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); + p->mm->context = 0; return 0; } -/* - * fill in the fpu structure for a core dump.. - * - * Actually this is "int dump_fpu (struct elf_fpregset_t *fpu)" - */ -int dump_fpu (int shutup_the_gcc_warning_about_elf_fpregset_t) +/* Fill in the fpu structure for a core dump.. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { - int fpvalid = 0; - /* - * To do... + /* We actually store the FPU info in the task->tss + * area. */ - - return fpvalid; + if(regs->cp0_status & ST0_CU1) { + memcpy(r, ¤t->tss.fpu, sizeof(current->tss.fpu)); + return 1; + } + return 0; /* Task didn't use the fpu at all. */ } -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) +/* Fill in the user structure for a core dump.. */ +void dump_thread(struct pt_regs *regs, struct user *dump) { - /* - * To do... - */ + dump->magic = CMAGIC; + dump->start_code = current->mm->start_code; + dump->start_data = current->mm->start_data; + dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1); + dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; + dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT; + dump->u_ssize = + (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT; + memcpy(&dump->regs[0], regs, sizeof(struct pt_regs)); + memcpy(&dump->regs[EF_SIZE/4], ¤t->tss.fpu, sizeof(current->tss.fpu)); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.1.43/linux/arch/mips/kernel/ptrace.c Tue May 13 22:41:02 1997 +++ linux/arch/mips/kernel/ptrace.c Thu Jun 26 12:33:37 1997 @@ -1,6 +1,7 @@ /* ptrace.c */ /* By Ross Biro 1/23/92 */ /* edited by Linus Torvalds */ +/* further hacked for MIPS by David S. Miller (dm@engr.sgi.com) */ #include #include @@ -8,79 +9,33 @@ #include #include #include +#include +#include #include -#include +#include #include +#include #include -#if 0 -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 - -/* set's the trap flag. */ -#define TRAP_FLAG 0x100 - -/* - * this is the number to subtract from the top of the stack. To find - * the local frame. - */ -#define MAGICNUMBER 68 - -/* - * this routine will get a word off of the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. - * this routine assumes that all the privileged stacks are in our - * data space. - */ -static inline int get_stack_long(struct task_struct *task, int offset) -{ - unsigned char *stack; - - stack = (unsigned char *)task->tss.esp0; - stack += offset; - return (*((int *)stack)); -} - -/* - * this routine will put a word on the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. - * this routine assumes that all the privileged stacks are in our - * data space. - */ -static inline int put_stack_long(struct task_struct *task, int offset, - unsigned long data) -{ - unsigned char * stack; - - stack = (unsigned char *) task->tss.esp0; - stack += offset; - *(unsigned long *) stack = data; - return 0; -} - /* * This routine gets a long from any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, * and that it is in the task area before calling this: this routine does * no checking. */ -static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr) +static unsigned long get_long(struct task_struct * tsk, + struct vm_area_struct * vma, unsigned long addr) { - pgd_t * pgdir; - pte_t * pgtable; - unsigned long page; + pgd_t *pgdir; + pmd_t *pgmiddle; + pte_t *pgtable; + unsigned long page, retval; repeat: - pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr); + pgdir = pgd_offset(vma->vm_mm, addr); if (pgd_none(*pgdir)) { - do_no_page(vma, addr, 0); + handle_mm_fault(tsk, vma, addr, 0); goto repeat; } if (pgd_bad(*pgdir)) { @@ -88,17 +43,29 @@ pgd_clear(pgdir); return 0; } - pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + handle_mm_fault(tsk, vma, addr, 0); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return 0; + } + pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - do_no_page(vma, addr, 0); + handle_mm_fault(tsk, vma, addr, 0); goto repeat; } page = pte_page(*pgtable); /* this is a hack for non-kernel-mapped video buffers and similar */ - if (page >= high_memory) + if (MAP_NR(page) >= MAP_NR(high_memory)) return 0; page += addr & ~PAGE_MASK; - return *(unsigned long *) page; + retval = *(unsigned long *) page; + flush_page_to_ram(page); + return retval; } /* @@ -110,17 +77,19 @@ * Now keeps R/W state of page so that a text page stays readonly * even if a debugger scribbles breakpoints into it. -M.U- */ -static void put_long(struct vm_area_struct * vma, unsigned long addr, +static void put_long(struct task_struct *tsk, + struct vm_area_struct * vma, unsigned long addr, unsigned long data) { pgd_t *pgdir; + pmd_t *pgmiddle; pte_t *pgtable; unsigned long page; repeat: - pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr); + pgdir = pgd_offset(vma->vm_mm, addr); if (!pgd_present(*pgdir)) { - do_no_page(vma, addr, 1); + handle_mm_fault(tsk, vma, addr, 1); goto repeat; } if (pgd_bad(*pgdir)) { @@ -128,23 +97,36 @@ pgd_clear(pgdir); return; } - pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + handle_mm_fault(tsk, vma, addr, 1); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return; + } + pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - do_no_page(vma, addr, 1); + handle_mm_fault(tsk, vma, addr, 1); goto repeat; } page = pte_page(*pgtable); if (!pte_write(*pgtable)) { - do_wp_page(vma, addr, 1); + handle_mm_fault(tsk, vma, addr, 1); goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ - if (page < high_memory) + flush_cache_page(vma, addr); + if (MAP_NR(page) < MAP_NR(high_memory)) { *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data; + flush_page_to_ram(page); + } /* 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))); - invalidate(); + flush_tlb_page(vma, addr); } static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr) @@ -152,7 +134,7 @@ struct vm_area_struct * vma; addr &= PAGE_MASK; - vma = find_vma(tsk, addr); + vma = find_vma(tsk->mm, addr); if (!vma) return NULL; if (vma->vm_start <= addr) @@ -186,8 +168,8 @@ if (!vma_high || vma_high->vm_start != vma->vm_end) return -EIO; } - low = get_long(vma, addr & ~(sizeof(long)-1)); - high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); + low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); + high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); switch (addr & (sizeof(long)-1)) { case 1: low >>= 8; @@ -204,7 +186,7 @@ } *result = low; } else - *result = get_long(vma, addr); + *result = get_long(tsk, vma, addr); return 0; } @@ -228,8 +210,8 @@ if (!vma_high || vma_high->vm_start != vma->vm_end) return -EIO; } - low = get_long(vma, addr & ~(sizeof(long)-1)); - high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); + low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); + high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); switch (addr & (sizeof(long)-1)) { case 0: /* shouldn't happen, but safety first */ low = data; @@ -253,50 +235,63 @@ high |= data >> 8; break; } - put_long(vma, addr & ~(sizeof(long)-1),low); - put_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high); + put_long(tsk, vma, addr & ~(sizeof(long)-1),low); + put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high); } else - put_long(vma, addr, data); + put_long(tsk, vma, addr, data); return 0; } -#endif asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { -#if 1 - return -ENOSYS; -#else struct task_struct *child; - struct user * dummy; - int i; - - - dummy = NULL; + int res; + lock_kernel(); +#if 0 + printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", + (int) request, (int) pid, (unsigned long) addr, + (unsigned long) data); +#endif if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) - return -EPERM; + if (current->flags & PF_PTRACED) { + res = -EPERM; + goto out; + } /* set the ptrace bit in the process flags. */ current->flags |= PF_PTRACED; - return 0; + res = 0; + goto out; + } + if (pid == 1) { /* you may not mess with init */ + res = -EPERM; + goto out; + } + if (!(child = find_task_by_pid(pid))) { + res = -ESRCH; + goto out; } - if (pid == 1) /* you may not mess with init */ - return -EPERM; - if (!(child = find_task_by_pid(pid))) - return -ESRCH; if (request == PTRACE_ATTACH) { - if (child == current) - return -EPERM; + if (child == current) { + res = -EPERM; + goto out; + } if ((!child->dumpable || (current->uid != child->euid) || + (current->uid != child->suid) || (current->uid != child->uid) || (current->gid != child->egid) || - (current->gid != child->gid)) && !suser()) - return -EPERM; + (current->gid != child->sgid) || + (current->gid != child->gid)) && !suser()) { + res = -EPERM; + goto out; + } /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) - return -EPERM; + if (child->flags & PF_PTRACED) { + res = -EPERM; + goto out; + } child->flags |= PF_PTRACED; if (child->p_pptr != current) { REMOVE_LINKS(child); @@ -304,142 +299,148 @@ SET_LINKS(child); } send_sig(SIGSTOP, child, 1); - return 0; + res = 0; + goto out; + } + if (!(child->flags & PF_PTRACED)) { + res = -ESRCH; + goto out; } - if (!(child->flags & PF_PTRACED)) - return -ESRCH; if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - return -ESRCH; + if (request != PTRACE_KILL) { + res = -ESRCH; + goto out; + } + } + if (child->p_pptr != current) { + res = -ESRCH; + goto out; } - if (child->p_pptr != current) - return -ESRCH; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; - int res; res = read_long(child, addr, &tmp); if (res < 0) - return res; - res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); - if (!res) - put_fs_long(tmp,(unsigned long *) data); - return res; + goto out; + res = put_user(tmp,(unsigned long *) data); + goto out; } /* read the word at location addr in the USER area. */ +/* #define DEBUG_PEEKUSR */ case PTRACE_PEEKUSR: { + struct pt_regs *regs; unsigned long tmp; - int res; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - return -EIO; - - res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); - if (res) - return res; - tmp = 0; /* Default return condition */ - if(addr < 17*sizeof(long)) { - addr = addr >> 2; /* temporary hack. */ - - tmp = get_stack_long(child, sizeof(long)*addr - MAGICNUMBER); - if (addr == DS || addr == ES || - addr == FS || addr == GS || - addr == CS || addr == SS) - tmp &= 0xffff; - }; - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 2; - tmp = child->debugreg[addr]; - }; - put_fs_long(tmp,(unsigned long *) data); - return 0; + regs = (struct pt_regs *) + (child->tss.ksp - sizeof(struct pt_regs)); + tmp = 0; /* Default return value. */ + if(addr < 32 && addr >= 0) { + tmp = regs->regs[addr]; + } else if(addr >= 32 && addr < 64) { + unsigned long long *fregs; + + /* We don't want to do a FPU operation here. */ + fregs = (unsigned long long *) + &child->tss.fpu.hard.fp_regs[0]; + tmp = (unsigned long) fregs[(addr - 32)]; + } else { + addr -= 64; + switch(addr) { + case 0: + tmp = regs->cp0_epc; + break; + case 1: + tmp = regs->cp0_cause; + break; + case 2: + tmp = regs->cp0_badvaddr; + break; + case 3: + tmp = regs->lo; + break; + case 4: + tmp = regs->hi; + break; + case 5: + tmp = child->tss.fpu.hard.control; + break; + case 6: + tmp = 0; + break; + default: + tmp = 0; + res = -EIO; + goto out; + }; + } + res = put_user(tmp, (unsigned long *) data); + goto out; } /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - return write_long(child,addr,data); - - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - return -EIO; + res = write_long(child,addr,data); + goto out; - addr = addr >> 2; /* temporary hack. */ - - if (addr == ORIG_EAX) - return -EIO; - if (addr == DS || addr == ES || - addr == FS || addr == GS || - addr == CS || addr == SS) { - data &= 0xffff; - if (data && (data & 3) != 3) - return -EIO; + case PTRACE_POKEUSR: { + struct pt_regs *regs; + int res = 0; + + regs = (struct pt_regs *) + (child->tss.ksp - sizeof(struct pt_regs)); + if(addr < 32 && addr >= 0) { + regs->regs[addr] = data; + } else if(addr >= 32 && addr < 64) { + unsigned long long *fregs; + + /* We don't want to do a FPU operation here. */ + fregs = (unsigned long long *) + &child->tss.fpu.hard.fp_regs[0]; + fregs[(addr - 32)] = (unsigned long long) data; + } else { + addr -= 64; + switch(addr) { + case 0: + regs->cp0_epc = data; + break; + case 3: + regs->lo = data; + break; + case 4: + regs->hi = data; + break; + case 5: + child->tss.fpu.hard.control = data; + break; + default: + /* The rest are not allowed. */ + res = -EIO; + break; + }; } - if (addr == EFL) { /* flags. */ - data &= FLAG_MASK; - data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER) & ~FLAG_MASK; - } - /* Do not allow the user to set the debug register for kernel - address space */ - if(addr < 17){ - if (put_stack_long(child, sizeof(long)*addr-MAGICNUMBER, data)) - return -EIO; - return 0; - }; - - /* We need to be very careful here. We implicitly - want to modify a portion of the task_struct, and we - have to be selective about what portions we allow someone - to modify. */ - - addr = addr << 2; /* Convert back again */ - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - - if(addr == (long) &dummy->u_debugreg[4]) return -EIO; - if(addr == (long) &dummy->u_debugreg[5]) return -EIO; - if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= 0xbffffffd) return -EIO; - - if(addr == (long) &dummy->u_debugreg[7]) { - data &= ~DR_CONTROL_RESERVED; - for(i=0; i<4; i++) - if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - return -EIO; - }; - - addr -= (long) &dummy->u_debugreg; - addr = addr >> 2; - child->debugreg[addr] = data; - return 0; - }; - return -EIO; + goto out; + } case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ - long tmp; - - if ((unsigned long) data > NSIG) - return -EIO; + if ((unsigned long) data > NSIG) { + res = -EIO; + goto out; + } if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; else child->flags &= ~PF_TRACESYS; child->exit_code = data; wake_up_process(child); - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG; - put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp); - return 0; + res = data; + goto out; } /* @@ -448,53 +449,36 @@ * exit. */ 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. */ - tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG; - put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp); - return 0; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long tmp; - - if ((unsigned long) data > NSIG) - return -EIO; - child->flags &= ~PF_TRACESYS; - tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG; - put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp); - wake_up_process(child); - child->exit_code = data; - /* give it a chance to run. */ - return 0; + if (child->state != TASK_ZOMBIE) { + wake_up_process(child); + child->exit_code = SIGKILL; + } + res = 0; + goto out; } case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - - if ((unsigned long) data > NSIG) - return -EIO; + if ((unsigned long) data > NSIG) { + res = -EIO; + goto out; + } child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); child->exit_code = data; REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG; - put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp); - return 0; + res = 0; + goto out; } default: - return -EIO; + res = -EIO; + goto out; } -#endif +out: + unlock_kernel(); + return res; } asmlinkage void syscall_trace(void) @@ -511,7 +495,10 @@ * for normal use. strace only continues with a signal if the * stopping signal is not SIGTRAP. -brl */ - if (current->exit_code) + if (current->exit_code) { + spin_lock_irq(¤t->sigmask_lock); current->signal |= (1 << (current->exit_code - 1)); + spin_unlock_irq(¤t->sigmask_lock); + } current->exit_code = 0; } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S --- v2.1.43/linux/arch/mips/kernel/r2300_fpu.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r2300_fpu.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,138 @@ +/* $Id: r2300_fpu.S,v 1.1 1997/06/06 09:32:55 ralf Exp $ + * r2300_fpu.S: Save/restore floating point context for signal handlers. + * + * 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) 1996 by Ralf Baechle + * + * Multi-arch abstraction and asm macros for easier reading: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include + + .set mips3 + .set noreorder + /* Save floating point context */ + .align 5 + LEAF(r2300_save_fp_context) + mfc0 t0,CP0_STATUS + sll t0,t0,2 + + bgez t0,1f + nop + + cfc1 t0,fcr31 + /* Store the 16 odd double precision registers */ + swc1 $f0,(SC_FPREGS+0)(a0) + swc1 $f1,(SC_FPREGS+8)(a0) + swc1 $f2,(SC_FPREGS+16)(a0) + swc1 $f3,(SC_FPREGS+24)(a0) + swc1 $f4,(SC_FPREGS+32)(a0) + swc1 $f5,(SC_FPREGS+40)(a0) + swc1 $f6,(SC_FPREGS+48)(a0) + swc1 $f7,(SC_FPREGS+56)(a0) + swc1 $f8,(SC_FPREGS+64)(a0) + swc1 $f9,(SC_FPREGS+72)(a0) + swc1 $f10,(SC_FPREGS+80)(a0) + swc1 $f11,(SC_FPREGS+88)(a0) + swc1 $f12,(SC_FPREGS+96)(a0) + swc1 $f13,(SC_FPREGS+104)(a0) + swc1 $f14,(SC_FPREGS+112)(a0) + swc1 $f15,(SC_FPREGS+120)(a0) + swc1 $f16,(SC_FPREGS+128)(a0) + swc1 $f17,(SC_FPREGS+136)(a0) + swc1 $f18,(SC_FPREGS+144)(a0) + swc1 $f19,(SC_FPREGS+152)(a0) + swc1 $f20,(SC_FPREGS+160)(a0) + swc1 $f21,(SC_FPREGS+168)(a0) + swc1 $f22,(SC_FPREGS+176)(a0) + swc1 $f23,(SC_FPREGS+184)(a0) + swc1 $f24,(SC_FPREGS+192)(a0) + swc1 $f25,(SC_FPREGS+200)(a0) + swc1 $f26,(SC_FPREGS+208)(a0) + swc1 $f27,(SC_FPREGS+216)(a0) + swc1 $f28,(SC_FPREGS+224)(a0) + swc1 $f29,(SC_FPREGS+232)(a0) + swc1 $f30,(SC_FPREGS+240)(a0) + swc1 $f31,(SC_FPREGS+248)(a0) + sw t0,SC_FPC_CSR(a0) + cfc1 t0,$0 # implementation/version + jr ra + .set nomacro + sw t0,SC_FPC_EIR(a0) + .set macro +1: + jr ra + .set nomacro + nop + .set macro + END(r2300_save_fp_context) + +/* Restore fpu state: + * - fp gp registers + * - cp1 status/control register + * + * We base the decission which registers to restore from the signal stack + * frame on the current content of c0_status, not on the content of the + * stack frame which might have been changed by the user. + */ + LEAF(r2300_restore_fp_context) + mfc0 t0,CP0_STATUS + sll t0,t0,2 + + bgez t0,1f + nop + + bgez t0,1f + lw t0,SC_FPC_CSR(a0) + /* Restore the 16 odd double precision registers only + * when enabled in the cp0 status register. + */ + ldc1 $f0,(SC_FPREGS+0)(a0) + ldc1 $f1,(SC_FPREGS+8)(a0) + ldc1 $f2,(SC_FPREGS+16)(a0) + ldc1 $f3,(SC_FPREGS+24)(a0) + ldc1 $f4,(SC_FPREGS+32)(a0) + ldc1 $f5,(SC_FPREGS+40)(a0) + ldc1 $f6,(SC_FPREGS+48)(a0) + ldc1 $f7,(SC_FPREGS+56)(a0) + ldc1 $f8,(SC_FPREGS+64)(a0) + ldc1 $f9,(SC_FPREGS+72)(a0) + ldc1 $f10,(SC_FPREGS+80)(a0) + ldc1 $f11,(SC_FPREGS+88)(a0) + ldc1 $f12,(SC_FPREGS+96)(a0) + ldc1 $f13,(SC_FPREGS+104)(a0) + ldc1 $f14,(SC_FPREGS+112)(a0) + ldc1 $f15,(SC_FPREGS+120)(a0) + ldc1 $f16,(SC_FPREGS+128)(a0) + ldc1 $f17,(SC_FPREGS+136)(a0) + ldc1 $f18,(SC_FPREGS+144)(a0) + ldc1 $f19,(SC_FPREGS+152)(a0) + ldc1 $f20,(SC_FPREGS+160)(a0) + ldc1 $f21,(SC_FPREGS+168)(a0) + ldc1 $f22,(SC_FPREGS+176)(a0) + ldc1 $f23,(SC_FPREGS+184)(a0) + ldc1 $f24,(SC_FPREGS+192)(a0) + ldc1 $f25,(SC_FPREGS+200)(a0) + ldc1 $f26,(SC_FPREGS+208)(a0) + ldc1 $f27,(SC_FPREGS+216)(a0) + ldc1 $f28,(SC_FPREGS+224)(a0) + ldc1 $f29,(SC_FPREGS+232)(a0) + ldc1 $f30,(SC_FPREGS+240)(a0) + ldc1 $f31,(SC_FPREGS+248)(a0) + jr ra + .set nomacro + ctc1 t0,fcr31 + .set macro +1: + jr ra + .set nomacro + nop + .set macro + END(r2300_restore_fp_context) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_misc.S linux/arch/mips/kernel/r2300_misc.S --- v2.1.43/linux/arch/mips/kernel/r2300_misc.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r2300_misc.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,397 @@ +/* $Id: r2300_misc.S,v 1.1 1997/06/06 09:32:57 ralf Exp $ + * r2300_misc.S: Misc. exception handling code for R3000/R2000. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-cpu abstraction reworking: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .text + .set mips1 + .set noreorder + + .align 5 + NESTED(r2300_handle_tlbl, PT_SIZE, sp) + .set noat + /* Check whether this is a refill or an invalid exception */ + mfc0 k0,CP0_BADVADDR + mfc0 k1,CP0_ENTRYHI + ori k0,0xfff # clear ASID... + xori k0,0xfff # in BadVAddr + andi k1,0xfc0 # get current ASID + or k0,k1 # make new entryhi + mfc0 k1,CP0_ENTRYHI + mtc0 k0,CP0_ENTRYHI + nop # for pipeline + nop + nop + tlbp + nop # for pipeline + nop + mfc0 k0,CP0_INDEX + + bgez k0,invalid_tlbl # bad addr in c0_badvaddr + mtc0 k1,CP0_ENTRYHI + + /* Damn... The next nop is required on the R4400PC V5.0, but + * I don't know why - at least there is no documented + * reason as for the others :-( + * And I haven't tested it as being necessary on R3000 - PMA. + * (The R3000 pipeline has only 5 stages, so it's probably not + * required -- Ralf) + */ + 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. + */ + /* used to be dmfc0 */ + mfc0 k0,CP0_BADVADDR + /* FIXME: This srl/sll sequence is as it is for the R4xx0, + * and I suspect that it should be different for + * the R[23]000. PMA + * (No, it's the assembler way to do + * k0 = k0 / PAGE_SIZE; + * k0 = k0 * sizeof(pte_t) + * Acutally the R4xx0 code will have to change when + * switching to 64 bit ... -- Ralf) + */ + srl k0,12 # get PFN? + 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 + + .set noat + SAVE_ALL + .set at + PRINT("Double fault caused by invalid entries in pgd:\n") + mfc0 a1,CP0_BADVADDR + PRINT("Double fault address : %08lx\n") + mfc0 a1,CP0_EPC + PRINT("c0_epc : %08lx\n") + + jal show_regs + move a0,sp + + jal dump_tlb_nonwired + nop + + mfc0 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. */ + mfc0 k1,CP0_CONTEXT + lw k0,(k1) # Never causes nested exception + mfc0 k1,CP0_EPC # get the return PC + srl k0,12 # Convert to EntryLo format + mtc0 k0,CP0_ENTRYLO0 + nop # for pipeline + tlbwr + nop # for pipeline + nop + nop + /* We don't know whether the original access was read or + * write, so return and see what happens... + */ + jr k1 + rfe + + /* 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 pipeline the tlbwi insn has been moved down. + * Moving it around is juggling with explosives... + */ + /* FIXME: Why is Ralf setting bit 3 of k1? This may need to + * be changed for R[236]000! PMA + * (The new ENTRYHI value will then point represent a + * inique virtual address outside the 32 bit address + * limit. This is just paranoia to avoid a tlb + * shutdown. This whole part of the routine is probably + * no longer required and can be removed -- Ralf) + */ + lui k1,0x0008 + or k0,k1 + sll k0,12 # make it EntryHi format + mtc0 k0,CP0_ENTRYHI + mtc0 zero,CP0_ENTRYLO0 +#endif + /* Test present bit in entry */ + mfc0 k0,CP0_BADVADDR + /* FIXME: This srl/sll sequence is as it is for the R4xx0, + * and I suspect that it should be different for + * the R[23]000. PMA + * (No, it's the assembler way to do + * k0 = k0 / PAGE_SIZE; + * k0 = k0 * sizeof(pte_t) + * Acutally the R4xx0 code will have to change when + * switching to 64 bit ... -- Ralf) + */ + 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 + lw k1,(k0) + + /* Present and read bits are set -> set valid and accessed bits */ + ori k1,(_PAGE_VALID|_PAGE_ACCESSED) + sw k1,(k0) + mfc0 k1,CP0_EPC + nop + + jr k1 + rfe + + /* 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 + mfc0 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 + + j ret_from_sys_call + nop + END(r2300_handle_tlbl) + + + .text + .align 5 + NESTED(r2300_handle_tlbs, PT_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 + */ + /* used to be dmfc0 */ + mfc0 k0,CP0_BADVADDR + /* FIXME: This srl/sll sequence is as it is for the R4xx0, + * and I suspect that it should be different for + * the R[23]000. PMA + */ + 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 + lw k1,(k0) + + /* Present and writable bits set: set accessed and dirty bits. */ + ori k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \ + _PAGE_VALID|_PAGE_DIRTY) + sw k1,(k0) + /* Now reload the entry into the TLB */ + /* FIXME: Why has Ralf set bit 2? Should it be different for + * R[23]000? PMA + * (The ori/xori combination actually _clears_ bit 2. + * This is required for the R4xx0 these CPUs always + * map page pairs; a page pair of 4k pages therfore + * has always an address with bit 2 set to zero. -- Ralf) + */ + ori k0,0x0004 + xori k0,0x0004 + lw k0,(k0) + srl k0,12 + mtc0 k0,CP0_ENTRYLO0 + mfc0 k1,CP0_EPC + nop # for pipeline + tlbwi + nop # for pipeline + nop + nop + + jr k1 + rfe + + /* 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 */ + /* FIXME: Why is Ralf setting bit 3 of k1? This may need to + * be changed for R[236]000! PMA + * (The new ENTRYHI value will then point represent a + * inique virtual address outside the 32 bit address + * limit. This is just paranoia to avoid a tlb + * shutdown. This whole part of the routine is probably + * no longer required and can be removed -- Ralf) + */ + lui k1,0x0008 + or k0,k1 + sll k0,12 + mtc0 k0,CP0_ENTRYHI + mtc0 zero,CP0_ENTRYLO0 + nop # for pipeline + nop # R4000 V2.2 requires 4 NOPs + nop + nop + tlbwi +#endif /* CONFIG_TLB_SHUTDOWN */ + .set noat + SAVE_ALL + mfc0 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 + + j ret_from_sys_call + nop + END(r2300_handle_tlbs) + + + .align 5 + NESTED(r2300_handle_mod, PT_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 + */ + /* used to be dmfc0 */ + mfc0 k0,CP0_BADVADDR + /* FIXME: This srl/sll sequence is as it is for the R4xx0, + * and I suspect that it should be different for + * the R[23]000. PMA + */ + 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 + lw k1,(k0) + + /* Present and writable bits set: set accessed and dirty bits. */ + ori k1,(_PAGE_ACCESSED|_PAGE_DIRTY) + sw k1,(k0) + /* Now reload the entry into the tlb */ + /* FIXME: Why has Ralf set bit 2? Should it be different for + * R[23]000? PMA + * (The ori/xori combination actually _clears_ bit 2. + * This is required for the R4xx0 these CPUs always + * map page pairs; a page pair of 4k pages therfore + * has always an address with bit 2 set to zero. -- Ralf) + */ + ori k0,0x0004 + xori k0,0x0004 + lw k0,(k0) + srl k0,12 + mtc0 k0,CP0_ENTRYLO0 + mfc0 k1,CP0_EPC + nop # for pipeline + nop + nop + tlbwi + nop # for pipeline + nop + nop + + jr k1 + rfe + END(r2300_handle_mod) + .set at diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_scall.S linux/arch/mips/kernel/r2300_scall.S --- v2.1.43/linux/arch/mips/kernel/r2300_scall.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r2300_scall.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,84 @@ +/* $Id: r2300_scall.S,v 1.1 1997/06/06 09:33:00 ralf Exp $ + * r2300_scall.S: R2000/R3000 specific code to handle system calls. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-arch abstraction and beautification: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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. + * + * 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 +NESTED(r2300_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,PT_R29(a0) # get old user stack pointer + +7: + lw t1,24(t0) # parameter #7 from usp + nop # delay slot + sw t1,24(sp) +6: + lw t1,20(t0) # parameter #6 from usp + nop # delay slot + sw t1,20(sp) +5: + lw t1,16(t0) # parameter #5 from usp + nop # delay slot + sw t1,16(sp) +4: + lw a3,PT_R7(a0) # 4 args +3: + lw a2,PT_R6(a0) # 3 args +2: + lw a1,PT_R5(a0) # 2 args +1: + jalr t2 # 1 args + lw a0,PT_R4(a0) + + lw ra,28(sp) + addiu sp,32 + jr ra + nop + +0: + jalr t2 # 0 args, just pass a0 + lw ra,28(sp) + addiu sp,32 + + jr ra + nop # delay slot + END(r2300_do_syscalls) + + .rdata + .align PTRLOG +dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b + + .section __ex_table,"a" + PTR 7b,bad_stack + PTR 6b,bad_stack + PTR 5b,bad_stack + .previous diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.1.43/linux/arch/mips/kernel/r2300_switch.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r2300_switch.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,100 @@ +/* $Id: r2300_switch.S,v 1.1 1997/06/06 09:33:02 ralf Exp $ + * r2300_switch.S: R3000/R2000 specific task switching code. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-cpu abstraction and macros for easier reading: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* XXX The following is fucking losing... find a better way dave. */ +MODE_ALIAS = 0x00e0 # uncachable, dirty, valid + + .text + .set mips3 +/* + * Code necessary to switch tasks on an Linux/MIPS machine. + * FIXME: We don't need to disable interrupts anymore. + */ + .align 5 + LEAF(r2300_resume) + GET_CURRENT(t0) + mfc0 t1,CP0_STATUS # Save status register + addu t0,a1 # Add tss offset + sw t1,THREAD_STATUS(t0) + ori t2,t1,0x1f # Disable interrupts + xori t2,0x1e + mtc0 t2,CP0_STATUS + CPU_SAVE_NONSCRATCH(t0) + sll t2,t1,2 # Save floating point state + bgez t2,2f + sw ra,THREAD_REG31(t0) + sll t2,t1,5 + bgez t2,1f + swc1 $f0, (THREAD_FPU + 0x00)(t0) + FPU_SAVE_16ODD(t0) +1: + FPU_SAVE_16EVEN(t0, t1) +2: + addu a0,a1 # Add tss offset + lw t0,THREAD_PGDIR(a0) # Switch the root pointer + li t1,TLB_ROOT # get PFN + mtc0 t1,CP0_ENTRYHI + mtc0 zero,CP0_INDEX + srl t0,12 # PFN is 12 bits west + ori t0,MODE_ALIAS # want uncachable, dirty, valid + mtc0 t0,CP0_ENTRYLO0 + lw a2,THREAD_STATUS(a0) + tlbwi + + /* Flush TLB. */ + mfc0 t3,CP0_STATUS # disable interrupts... + ori t4,t3,1 + xori t4,1 + mtc0 t4,CP0_STATUS + lw t0,mips_tlb_entries + mtc0 zero,CP0_ENTRYLO0 +1: + subu t0,1 + mtc0 t0,CP0_INDEX + lui t1,0x0008 + or t1,t0,t1 + sll t1,12 + mtc0 t1,CP0_ENTRYHI + bne t2,t0,1b + tlbwi + + ori t1,a2,1 # Restore FPU, pipeline magic + xori t1,1 + mtc0 t1,CP0_STATUS + sll t0,a2,2 + bgez t0,2f + sll t0,a2,5 + bgez t0,1f + lwc1 $f0, (THREAD_FPU + 0x00)(a0) + FPU_RESTORE_16ODD(a0) +1: + FPU_RESTORE_16EVEN(a0, t0) +2: + CPU_RESTORE_NONSCRATCH(a0) + lw t0,THREAD_KSP(a0) # Restore status register + sw t0,kernelsp + jr ra + mtc0 a2,CP0_STATUS + END(r2300_resume) + + diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S --- v2.1.43/linux/arch/mips/kernel/r4k_fpu.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r4k_fpu.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,148 @@ +/* $Id: r4k_fpu.S,v 1.1 1997/06/06 09:33:04 ralf Exp $ + * r4k_fpu.S: Save/restore floating point context for signal handlers. + * + * 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) 1996 by Ralf Baechle + * + * Multi-arch abstraction and asm macros for easier reading: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include + + .set noreorder + .set mips3 + /* Save floating point context */ + LEAF(r4k_save_fp_context) + mfc0 t1,CP0_STATUS + sll t2,t1,2 + bgez t2,2f + sll t2,t1,5 + + cfc1 t1,fcr31 + bgez t2,1f + nop + /* Store the 16 odd double precision registers */ + swc1 $f1,(SC_FPREGS+8)(a0) + swc1 $f3,(SC_FPREGS+24)(a0) + swc1 $f5,(SC_FPREGS+40)(a0) + swc1 $f7,(SC_FPREGS+56)(a0) + swc1 $f9,(SC_FPREGS+72)(a0) + swc1 $f11,(SC_FPREGS+88)(a0) + swc1 $f13,(SC_FPREGS+104)(a0) + swc1 $f15,(SC_FPREGS+120)(a0) + swc1 $f17,(SC_FPREGS+136)(a0) + swc1 $f19,(SC_FPREGS+152)(a0) + swc1 $f21,(SC_FPREGS+168)(a0) + swc1 $f23,(SC_FPREGS+184)(a0) + swc1 $f25,(SC_FPREGS+200)(a0) + swc1 $f27,(SC_FPREGS+216)(a0) + swc1 $f29,(SC_FPREGS+232)(a0) + swc1 $f31,(SC_FPREGS+248)(a0) + + /* Store the 16 even double precision registers */ +1: + swc1 $f0,(SC_FPREGS+0)(a0) + swc1 $f2,(SC_FPREGS+16)(a0) + swc1 $f4,(SC_FPREGS+32)(a0) + swc1 $f6,(SC_FPREGS+48)(a0) + swc1 $f8,(SC_FPREGS+64)(a0) + swc1 $f10,(SC_FPREGS+80)(a0) + swc1 $f12,(SC_FPREGS+96)(a0) + swc1 $f14,(SC_FPREGS+112)(a0) + swc1 $f16,(SC_FPREGS+128)(a0) + swc1 $f18,(SC_FPREGS+144)(a0) + swc1 $f20,(SC_FPREGS+160)(a0) + swc1 $f22,(SC_FPREGS+176)(a0) + swc1 $f24,(SC_FPREGS+192)(a0) + swc1 $f26,(SC_FPREGS+208)(a0) + swc1 $f28,(SC_FPREGS+224)(a0) + swc1 $f30,(SC_FPREGS+240)(a0) + sw t1,SC_FPC_CSR(a0) + cfc1 t0,$0 # implementation/version + + jr ra + .set nomacro + sw t0,SC_FPC_EIR(a0) + .set macro +2: + jr ra + .set nomacro + nop + .set macro + END(r4k_save_fp_context) + +/* Restore fpu state: + * - fp gp registers + * - cp1 status/control register + * + * We base the decission which registers to restore from the signal stack + * frame on the current content of c0_status, not on the content of the + * stack frame which might have been changed by the user. + */ + LEAF(r4k_restore_fp_context) + mfc0 t1,CP0_STATUS + sll t0,t1,2 + bgez t0,2f + sll t0,t1,5 + + bgez t0,1f + lw t0,SC_FPC_CSR(a0) + /* Restore the 16 odd double precision registers only + * when enabled in the cp0 status register. + */ + lwc1 $f1,(SC_FPREGS+8)(a0) + lwc1 $f3,(SC_FPREGS+24)(a0) + lwc1 $f5,(SC_FPREGS+40)(a0) + lwc1 $f7,(SC_FPREGS+56)(a0) + lwc1 $f9,(SC_FPREGS+72)(a0) + lwc1 $f11,(SC_FPREGS+88)(a0) + lwc1 $f13,(SC_FPREGS+104)(a0) + lwc1 $f15,(SC_FPREGS+120)(a0) + lwc1 $f17,(SC_FPREGS+136)(a0) + lwc1 $f19,(SC_FPREGS+152)(a0) + lwc1 $f21,(SC_FPREGS+168)(a0) + lwc1 $f23,(SC_FPREGS+184)(a0) + lwc1 $f25,(SC_FPREGS+200)(a0) + lwc1 $f27,(SC_FPREGS+216)(a0) + lwc1 $f29,(SC_FPREGS+232)(a0) + lwc1 $f31,(SC_FPREGS+248)(a0) + + /* Restore the 16 even double precision registers + * when cp1 was enabled in the cp0 status register. + */ +1: + lwc1 $f0,(SC_FPREGS+0)(a0) + lwc1 $f2,(SC_FPREGS+16)(a0) + lwc1 $f4,(SC_FPREGS+32)(a0) + lwc1 $f6,(SC_FPREGS+48)(a0) + lwc1 $f8,(SC_FPREGS+64)(a0) + lwc1 $f10,(SC_FPREGS+80)(a0) + lwc1 $f12,(SC_FPREGS+96)(a0) + lwc1 $f14,(SC_FPREGS+112)(a0) + lwc1 $f16,(SC_FPREGS+128)(a0) + lwc1 $f18,(SC_FPREGS+144)(a0) + lwc1 $f20,(SC_FPREGS+160)(a0) + lwc1 $f22,(SC_FPREGS+176)(a0) + lwc1 $f24,(SC_FPREGS+192)(a0) + lwc1 $f26,(SC_FPREGS+208)(a0) + lwc1 $f28,(SC_FPREGS+224)(a0) + lwc1 $f30,(SC_FPREGS+240)(a0) + ctc1 t0,fcr31 + + jr ra + .set nomacro + nop + .set macro +2: + jr ra + .set nomacro + nop + .set macro + END(r4k_restore_fp_context) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S --- v2.1.43/linux/arch/mips/kernel/r4k_misc.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r4k_misc.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,189 @@ +/* $Id: r4k_misc.S,v 1.2 1997/06/12 14:18:10 ralf Exp $ + * r4k_misc.S: Misc. exception handling code for r4k. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-cpu abstraction and reworking: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOTLB_OPTIMIZE /* If you are paranoid, define this. */ + + /* ABUSE of CPP macros 101. */ + + /* After this macro runs, the pte faulted on is + * in register PTE, a ptr into the table in which + * the pte belongs is in PTR. + */ +#define LOAD_PTE(pte, ptr) \ + mfc0 pte, CP0_BADVADDR; \ + srl pte, pte, 22; \ + _GET_CURRENT(ptr); \ + sll pte, pte, 2; \ + lw ptr, THREAD_PGDIR(ptr); \ + addu ptr, pte, ptr; \ + mfc0 pte, CP0_BADVADDR; \ + lw ptr, (ptr); \ + srl pte, pte, 10; \ + and pte, pte, 0xffc; \ + addu ptr, ptr, pte; \ + lw pte, (ptr); + + /* This places the even/odd pte pair in the page + * table at PTR into ENTRYLO0 and ENTRYLO1 using + * TMP as a scratch register. + */ +#define PTE_RELOAD(ptr, tmp) \ + ori ptr, ptr, 0x4; \ + xori ptr, ptr, 0x4; \ + lw tmp, 4(ptr); \ + lw ptr, 0(ptr); \ + srl tmp, tmp, 6; \ + mtc0 tmp, CP0_ENTRYLO1; \ + srl ptr, ptr, 6; \ + mtc0 ptr, CP0_ENTRYLO0; + +#define DO_FAULT(write) \ + .set noat; \ + .set macro; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ + STI; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ + li a1, write; \ + j ret_from_sys_call; \ + nop; \ + .set noat; \ + .set nomacro; + + /* Check is PTE is present, if not then jump to LABEL. + * PTR points to the page table where this PTE is located, + * when the macro is done executing PTE will be restored + * with it's original value. + */ +#define PTE_PRESENT(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + bnez pte, label; \ + lw pte, (ptr); + + /* Make PTE valid, store result in PTR. */ +#define PTE_MAKEVALID(pte, ptr) \ + ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ + sw pte, (ptr); + + /* Check if PTE can be written to, if not branch to LABEL. + * Regardless restore PTE with value from PTR when done. + */ +#define PTE_WRITABLE(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + bnez pte, label; \ + lw pte, (ptr); + + /* Make PTE writable, update software status bits as well, + * then store at PTR. + */ +#define PTE_MAKEWRITE(pte, ptr) \ + ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ + _PAGE_VALID | _PAGE_DIRTY); \ + sw pte, (ptr); + + .set noreorder + .set mips3 + + /* Note for many R4k variants tlb probes cannot be executed out + * of the instruction cache else you get bogus results. + */ + + .align 5 + NESTED(r4k_handle_tlbl, PT_SIZE, sp) + .set noat + .set nomacro +invalid_tlbl: +#ifndef NOTLB_OPTIMIZE + /* Test present bit in entry. */ + LOAD_PTE(k0, k1) + tlbp + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + eret +#endif + +nopage_tlbl: + DO_FAULT(0) + END(r4k_handle_tlbl) + + .align 5 + NESTED(r4k_handle_tlbs, PT_SIZE, sp) + .set noat +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + eret +#endif + +nopage_tlbs: + DO_FAULT(1) + END(r4k_handle_tlbs) + + .align 5 + NESTED(r4k_handle_mod, PT_SIZE, sp) + .set noat +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + andi k0, k0, _PAGE_WRITE + beqz k0, nowrite_mod + lw k0, (k1) + + /* Present and writable bits set, set accessed and dirty bits. */ + PTE_MAKEWRITE(k0, k1) +#if 0 + ori k0, k0, (_PAGE_ACCESSED | _PAGE_DIRTY) + sw k0, (k1) +#endif + + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + eret +#endif + +nowrite_mod: + DO_FAULT(1) + END(r4k_handle_mod) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_scall.S linux/arch/mips/kernel/r4k_scall.S --- v2.1.43/linux/arch/mips/kernel/r4k_scall.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r4k_scall.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,72 @@ +/* $Id: r4k_scall.S,v 1.1 1997/06/06 09:33:08 ralf Exp $ + * r4k_scall.S: R4xx0 specific code to handle system calls. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-arch abstraction and beautification: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .set noreorder + .set mips3 + .align 5 +NESTED(r4k_do_syscalls, 64, sp) + subu sp, 64 + sw ra, 56(sp) + sll a2, a2, PTRLOG + lw t0, dst(a2) + move t2, a1 + jalr t0 + lw t0, PT_R29(a0) # get old user stack pointer +7: + lw t1, 24(t0) # parameter #7 from usp + sw t1, 24(sp) +6: + lw t1, 20(t0) # parameter #6 from usp + sw t1, 20(sp) +5: + lw t1, 16(t0) # parameter #5 from usp + sw t1, 16(sp) +4: + lw a3, PT_R7(a0) # 4 args +3: + lw a2, PT_R6(a0) # 3 args +2: + lw a1, PT_R5(a0) # 2 args +1: + jalr t2 # 1 args + lw a0, PT_R4(a0) + + .set reorder + lw ra, 56(sp) + addiu sp, 64 + jr ra +0: + jalr t2 # 0 args, just pass a0 + nop + lw ra, 56(sp) + addiu sp, 64 + jr ra + nop + END(r4k_do_syscalls) + + .rdata + .align PTRLOG +dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b + + .section __ex_table,"a" + PTR 7b,bad_stack + PTR 6b,bad_stack + PTR 5b,bad_stack + .previous diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.1.43/linux/arch/mips/kernel/r4k_switch.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r4k_switch.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,68 @@ +/* + * r4k_switch.S: R4xx0 specific task switching code. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-cpu abstraction and macros for easier reading: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + .set noreorder + .set mips3 + .align 5 + LEAF(r4xx0_resume) + GET_CURRENT(t0) + mfc0 t1, CP0_STATUS + nop + sw t1, THREAD_STATUS(t0) + ori t2, t1, 0x1f + xori t2, t2, 0x1e + mtc0 t2, CP0_STATUS + CPU_SAVE_NONSCRATCH(t0) + sll t2, t1, 2 # Save floating point state + bgez t2, 2f + sw ra, THREAD_REG31(t0) + sll t2, t1, 5 + bgez t2, 1f + swc1 $f0, (THREAD_FPU + 0x00)(t0) + FPU_SAVE_16ODD(t0) +1: + FPU_SAVE_16EVEN(t0, t1) # clobbers t1 +2: + lw a3, TASK_MM(a0) + lw a2, THREAD_STATUS(a0) + lw a3, MM_CONTEXT(a3) + ori t1, a2, 1 # restore fpu, pipeline magic + andi a3, a3, 0xff + xori t1, t1, 1 + mtc0 a3, CP0_ENTRYHI + mtc0 t1, CP0_STATUS + sll t0, a2, 2 + bgez t0, 2f + sll t0, a2, 5 + bgez t0, 1f + lwc1 $f0, (THREAD_FPU + 0x00)(a0) + FPU_RESTORE_16ODD(a0) +1: + FPU_RESTORE_16EVEN(a0, t0) # clobbers t0 +2: + CPU_RESTORE_NONSCRATCH(a0) + lw t0, THREAD_KSP(a0) + sw t0, kernelsp + jr ra + mtc0 a2, CP0_STATUS + END(r4xx0_resume) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4xx0.S linux/arch/mips/kernel/r4xx0.S --- v2.1.43/linux/arch/mips/kernel/r4xx0.S Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/kernel/r4xx0.S Wed Dec 31 16:00:00 1969 @@ -1,829 +0,0 @@ -/* - * 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 (coprocessor 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) nonexistent 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 unnecessary - * 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 sure 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 v2.1.43/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S --- v2.1.43/linux/arch/mips/kernel/r6000_fpu.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/r6000_fpu.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,100 @@ +/* $Id: r6000_fpu.S,v 1.1 1997/06/06 09:33:14 ralf Exp $ + * r6000_fpu.S: Save/restore floating point context for signal handlers. + * + * 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) 1996 by Ralf Baechle + * + * Multi-arch abstraction and asm macros for easier reading: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include +#include +#include + + .set noreorder + /* Save floating point context */ + LEAF(r6000_save_fp_context) + mfc0 t0,CP0_STATUS + sll t0,t0,2 + bgez t0,1f + nop + + cfc1 t1,fcr31 + /* Store the 16 double precision registers */ + sdc1 $f0,(SC_FPREGS+0)(a0) + sdc1 $f2,(SC_FPREGS+16)(a0) + sdc1 $f4,(SC_FPREGS+32)(a0) + sdc1 $f6,(SC_FPREGS+48)(a0) + sdc1 $f8,(SC_FPREGS+64)(a0) + sdc1 $f10,(SC_FPREGS+80)(a0) + sdc1 $f12,(SC_FPREGS+96)(a0) + sdc1 $f14,(SC_FPREGS+112)(a0) + sdc1 $f16,(SC_FPREGS+128)(a0) + sdc1 $f18,(SC_FPREGS+144)(a0) + sdc1 $f20,(SC_FPREGS+160)(a0) + sdc1 $f22,(SC_FPREGS+176)(a0) + sdc1 $f24,(SC_FPREGS+192)(a0) + sdc1 $f26,(SC_FPREGS+208)(a0) + sdc1 $f28,(SC_FPREGS+224)(a0) + sdc1 $f30,(SC_FPREGS+240)(a0) + sw t0,SC_FPC_CSR(a0) + cfc1 t0,$0 # implementation/version + + jr ra + .set nomacro + sw t0,SC_FPC_EIR(a0) + .set macro +1: + jr ra + .set nomacro + nop + .set macro + END(r6000_save_fp_context) + +/* Restore fpu state: + * - fp gp registers + * - cp1 status/control register + * + * We base the decission which registers to restore from the signal stack + * frame on the current content of c0_status, not on the content of the + * stack frame which might have been changed by the user. + */ + LEAF(r6000_restore_fp_context) + mfc0 t0,CP0_STATUS + sll t0,t0,2 + + bgez t0,1f + lw t0,SC_FPC_CSR(a0) + /* Restore the 16 double precision registers */ + ldc1 $f0,(SC_FPREGS+0)(a0) + ldc1 $f2,(SC_FPREGS+16)(a0) + ldc1 $f4,(SC_FPREGS+32)(a0) + ldc1 $f6,(SC_FPREGS+48)(a0) + ldc1 $f8,(SC_FPREGS+64)(a0) + ldc1 $f10,(SC_FPREGS+80)(a0) + ldc1 $f12,(SC_FPREGS+96)(a0) + ldc1 $f14,(SC_FPREGS+112)(a0) + ldc1 $f16,(SC_FPREGS+128)(a0) + ldc1 $f18,(SC_FPREGS+144)(a0) + ldc1 $f20,(SC_FPREGS+160)(a0) + ldc1 $f22,(SC_FPREGS+176)(a0) + ldc1 $f24,(SC_FPREGS+192)(a0) + ldc1 $f26,(SC_FPREGS+208)(a0) + ldc1 $f28,(SC_FPREGS+224)(a0) + ldc1 $f30,(SC_FPREGS+240)(a0) + + jr ra + .set nomacro + ctc1 t0,fcr31 + .set macro +1: + jr ra + .set nomacro + nop + .set macro + END(r6000_restore_fp_context) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/reset.c linux/arch/mips/kernel/reset.c --- v2.1.43/linux/arch/mips/kernel/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/reset.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,30 @@ +/* + * linux/arch/mips/sni/process.c + * + * Reset the machine. + */ +#include +#include +#include +#include + +/* + * Urgs ... Too many MIPS machines to handle this in a generic way. + * So handle all using function pointers to machine specific + * functions. + */ + +void machine_restart(char *command) +{ + _machine_restart(command); +} + +void machine_halt(void) +{ + _machine_halt(); +} + +void machine_power_off(void) +{ + _machine_power_off(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.1.43/linux/arch/mips/kernel/setup.c Thu Dec 21 02:05:17 1995 +++ linux/arch/mips/kernel/setup.c Thu Jun 26 12:33:37 1997 @@ -2,11 +2,13 @@ * linux/arch/mips/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1995 Ralf Baechle + * Copyright (C) 1995, 1996 Ralf Baechle + * Copyright (C) 1996 Stoned Elipot */ #include -#include #include +#include +#include #include #include #include @@ -15,198 +17,87 @@ #include #include #include -#include #include +#include #include #include +#ifdef CONFIG_BLK_DEV_RAM +#include +#endif +#ifdef CONFIG_RTC +#include +#include +#endif #include #include +#include +#include #include -#include #include #include +#ifdef CONFIG_SGI +#include +#endif /* * 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. + * What to do to keep the caches consistent with memory + * We don't use the normal cacheflush routine to keep Tyne caches happier. */ -unsigned char jazz_rtc_read_data(void); -void jazz_rtc_write_data(unsigned char data); +void (*fd_cacheflush)(const void *addr, size_t size); -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. + * Not all of the MIPS CPUs have the "wait" instruction available. This + * is set to true if it is available. The wait instruction stops the + * pipeline and reduces the power consumption of the CPU very much. */ -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 +char wait_available; /* - * Tell us the machine setup.. + * There are several bus types available for MIPS machines. "RISC PC" + * type machines have ISA, EISA, VLB or PCI available, DECstations + * have Turbochannel or Q-Bus, SGI has GIO, there are lots of VME + * boxes ... + * This flag is set if a EISA slots are available. */ -char wait_available; /* set if the "wait" instruction available */ +int EISA_bus = 0; /* - * Bus types .. + * Milo passes some information to the kernel that looks like as if it + * had been returned by a Intel PC BIOS. Milo doesn't fill the passed + * drive_info and Linux can find out about this anyway, so I'm going to + * remove this sometime. screen_info contains information about the + * resolution of the text screen. For VGA graphics based machine this + * information is being use to continue the screen output just below + * the BIOS printed text and with the same text resolution. */ -int EISA_bus = 0; +struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO; +struct screen_info screen_info = DEFAULT_SCREEN_INFO; /* - * Setup options + * setup informations + * + * These are intialized so they are in the .data section */ -struct drive_info_struct drive_info; -struct screen_info screen_info = SCREEN_INFO; +unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */ +unsigned long mips_cputype = CPU_UNKNOWN; +unsigned long mips_machtype = MACH_UNKNOWN; +unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; +unsigned long mips_tlb_entries = 48; /* Guess which CPU I've got :) */ +unsigned long mips_vram_base = KSEG0; unsigned char aux_device_present; -extern int ramdisk_size; extern int root_mountflags; extern int _end; extern char empty_zero_page[PAGE_SIZE]; /* - * Initialise this structure so that it will be placed in the - * .data section of the object file - */ -struct bootinfo boot_info = BOOT_INFO; - -/* * This is set up by the setup-routine at boot-time */ #define PARAM empty_zero_page @@ -214,137 +105,142 @@ #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC)) #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF)) #endif +#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) +#define KERNEL_START (*(unsigned long *) (PARAM+0x214)) +#define INITRD_START (*(unsigned long *) (PARAM+0x218)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) static char command_line[CL_SIZE] = { 0, }; char saved_command_line[CL_SIZE]; -#if 0 /* - * Code for easy access to new style bootinfo - * - * Parameter: tag -- taglist entry - * - * returns : (tag *) -- pointer to taglist entry, NULL for not found + * The board specific setup routine sets irq_setup to point to a board + * specific setup routine. */ -tag * -bi_TagFind(enum bi_tag tag) -{ - /* TBD */ - return 0; -} +void (*irq_setup)(void); /* - * Only for taglist creators (bootloaders) - * - * Parameter: tag -- (enum bi_tag) taglist entry - * - * returns : 1 -- success - * 0 -- failure + * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped + * for the processor. */ -int -bi_TagAdd(enum bi_tag tag, unsigned long size, void *tagdata) +unsigned long isa_slot_offset; + +__initfunc(static void default_irq_setup(void)) { - /* TBD */ - return 0; + panic("Unknown machtype in init_IRQ"); } -#endif /* 0 */ -void setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p) +__initfunc(static void default_fd_cacheflush(const void *addr, size_t size)) { - unsigned long memory_start, memory_end; +} + +__initfunc(void setup_arch(char **cmdline_p, + unsigned long * memory_start_p, unsigned long * memory_end_p)) +{ + unsigned long memory_end; + tag* atag; + void decstation_setup(void); + void deskstation_setup(void); + void jazz_setup(void); + void sni_rm200_pci_setup(void); + void sgi_setup(void); + + /* Perhaps a lot of tags are not getting 'snarfed' - */ + /* please help yourself */ + + atag = bi_TagFind(tag_machtype); + memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); + + atag = bi_TagFind(tag_machgroup); + memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); + + atag = bi_TagFind(tag_vram_base); + memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size); - switch(boot_info.machtype) + irq_setup = default_irq_setup; + fd_cacheflush = default_fd_cacheflush; + + switch(mips_machgroup) { -#ifdef CONFIG_ACER_PICA_61 - case MACH_ACER_PICA_61: - feature = &acer_pica_61_feature; +#ifdef CONFIG_MIPS_DECSTATION + case MACH_GROUP_DEC: + decstation_setup(); break; #endif -#ifdef CONFIG_DECSTATION - case MACH_DECSTATION: - feature = &decstation_feature; +#if defined(CONFIG_MIPS_ARC) +/* Perhaps arch/mips/deskstation should be renommed arch/mips/arc. + * For now CONFIG_MIPS_ARC means DeskStation. -Stoned. + */ + case MACH_GROUP_ARC: + deskstation_setup(); break; #endif -#ifdef CONFIG_DESKSTATION_RPC - case MACH_DESKSTATION_RPC: - feature = &deskstation_rpc44_feature; +#ifdef CONFIG_MIPS_JAZZ + case MACH_GROUP_JAZZ: + jazz_setup(); break; #endif -#ifdef CONFIG_DESKSTATION_TYNE - case MACH_DESKSTATION_TYNE: - feature = &deskstation_tyne_feature; +#ifdef CONFIG_SGI + case MACH_GROUP_SGI: + sgi_setup(); break; #endif -#ifdef CONFIG_MIPS_MAGNUM_4000 - case MACH_MIPS_MAGNUM_4000: - feature = &mips_magnum_4000_feature; +#ifdef CONFIG_SNI_RM200_PCI + case MACH_GROUP_SNI_RM: + sni_rm200_pci_setup(); 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 -/* ROOT_DEV = to_kdev_t(0x00ff); */ /* NFS */ -#endif - memcpy(&drive_info, &boot_info.drive_info, sizeof(drive_info)); + atag = bi_TagFind(tag_drive_info); + memcpy(&drive_info, TAGVALPTR(atag), atag->size); #if 0 aux_device_present = AUX_DEVICE_INFO; #endif - memory_end = boot_info.memupper; + + memory_end = mips_memory_upper; + /* + * Due to prefetching and similar mechanism the CPU sometimes + * generates addresses beyond the end of memory. We leave the size + * of one cache line at the end of memory unused to make shure we + * don't catch this type of bus errors. + */ + memory_end -= 128; memory_end &= PAGE_MASK; - ramdisk_size = boot_info.ramdisk_size; - if (boot_info.mount_root_rdonly) - root_mountflags |= MS_RDONLY; - memory_start = (unsigned long) &_end; - memory_start += (ramdisk_size << 10); +#ifdef CONFIG_BLK_DEV_RAM + 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); +#endif + + atag = bi_TagFind(tag_mount_root_rdonly); + if (atag) + root_mountflags |= MS_RDONLY; + + atag = bi_TagFind(tag_command_line); + if (atag) + memcpy(&command_line, TAGVALPTR(atag), atag->size); memcpy(saved_command_line, command_line, CL_SIZE); saved_command_line[CL_SIZE-1] = '\0'; *cmdline_p = command_line; - *memory_start_p = memory_start; + *memory_start_p = (unsigned long) &_end; *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"); +#ifdef CONFIG_BLK_DEV_INITRD + if (LOADER_TYPE) { + initrd_start = INITRD_START; + initrd_end = INITRD_START+INITRD_SIZE; + if (initrd_end > memory_end) { + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + initrd_end,memory_end); + initrd_start = 0; + } } #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 v2.1.43/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.1.43/linux/arch/mips/kernel/signal.c Sun Jan 26 02:07:05 1997 +++ linux/arch/mips/kernel/signal.c Thu Jun 26 12:33:37 1997 @@ -2,7 +2,9 @@ * linux/arch/mips/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1994, 1995, 1996 Ralf Baechle */ +#include #include #include #include @@ -14,109 +16,98 @@ #include #include +#include #include -#include -#include +#include +#include #define _S(nr) (1<<((nr)-1)) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); +extern asmlinkage void (*save_fp_context)(struct sigcontext *sc); +extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc); /* - * atomically swap in the new signal mask, and wait for a signal. + * Atomically swap in the new signal mask, and wait for a signal. + * Unlike on Intel we pass a sigset_t *, not sigset_t. */ -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set) +asmlinkage int sys_sigsuspend(struct pt_regs *regs) { unsigned long mask; - struct pt_regs * regs; - int ret = -EINTR; + sigset_t *uset, set; - lock_kernel(); - regs = (struct pt_regs *) &restart; + uset = (sigset_t *)(long) regs->regs[4]; + if (get_user(set, uset)) + return -EFAULT; + + spin_lock_irq(¤t->sigmask_lock); mask = current->blocked; current->blocked = set & _BLOCKABLE; - regs->reg2 = -EINTR; + spin_unlock_irq(¤t->sigmask_lock); + + regs->regs[2] = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(mask,regs)) - goto out; + if (do_signal(mask, regs)) + return -EINTR; } -out: - unlock_kernel(); - return ret; + return -EINTR; } -/* - * This sets regs->reg29 even though we don't actually use sigstacks yet.. - */ asmlinkage int sys_sigreturn(struct pt_regs *regs) { - struct sigcontext_struct *context; - int ret; + struct sigcontext *context; + int i; - lock_kernel(); - /* - * 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)) + context = (struct sigcontext *)(long) regs->regs[29]; + if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || + (regs->regs[29] & (SZREG - 1))) goto badframe; - 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; + current->blocked = context->sc_sigset & _BLOCKABLE; + regs->cp0_epc = context->sc_pc; + /* - * Skip k0/k1 + * We only allow user processes in 64bit mode (n32, 64 bit ABI) to + * restore the upper half of registers. */ - 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; + if (read_32bit_cp0_register(CP0_STATUS) & ST0_UX) + for(i = 31;i >= 0;i--) + __get_user(regs->regs[i], &context->sc_regs[i]); + else + for(i = 31;i >= 0;i--) { + __get_user(regs->regs[i], &context->sc_regs[i]); + regs->regs[i] = (int) regs->regs[i]; + } + + __get_user(regs->hi, &context->sc_mdhi); + __get_user(regs->lo, &context->sc_mdlo); + restore_fp_context(context); /* - * disable syscall checks + * Disable syscall checks */ regs->orig_reg2 = -1; - goto out; + + /* + * Don't let your children do this ... + */ + __asm__ __volatile__( + "move\t$29,%0\n\t" + "j\tret_from_sys_call" + :/* no outputs */ + :"r" (regs)); + /* Unreached */ badframe: + lock_kernel(); do_exit(SIGSEGV); -out: - ret = context->sc_v0; unlock_kernel(); - return ret; } /* @@ -137,14 +128,14 @@ * 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 + * arg save space ; 16/32 bytes arg. save space + * code1 (addiu sp,#1-offset) ; pop stackframe * 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 + * #1| $0, at, v0, v1, a0, a1, a2, a3 ; All integer registers + * | t0, t1, t2, t3, t4, t5, t6, t7 ; $0, k0 and k1 are placeholders * | s0, s1, s2, s3, s4, s5, s6, s7 - * | t8, t9, gp, sp, fp, ra; + * | k0, k1, t8, t9, gp, sp, fp, ra; * | epc ; old program counter * | cause ; CP0 cause register * | oldmask @@ -153,27 +144,25 @@ struct sc { unsigned long ass[4]; unsigned int code[4]; - struct sigcontext_struct scc; + struct sigcontext 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, +static void setup_frame(struct sigaction * sa, struct pt_regs *regs, int signr, unsigned long oldmask) { struct sc *frame; + struct sigcontext *sc; + int i; - frame = *fp; + /* Align the stackframe to an adequate boundary for the architecture. */ + frame = (struct sc *) (long) regs->regs[29]; frame--; + frame = (struct sc *)((unsigned long)frame & ALMASK); - /* - * 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. - */ - if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) || - ((unsigned long)frame & 3)) - do_exit(SIGSEGV); + if (verify_area(VERIFY_WRITE, frame, sizeof (*frame))) + goto segv_and_exit; + sc = &frame->scc; /* * Set up the return code ... @@ -184,64 +173,83 @@ * syscall * .set reorder */ - frame->code[0] = 0x27bd0000 + scc_offset; - frame->code[1] = 0x24020000 + __NR_sigreturn; - frame->code[2] = 0x0000000c; + __put_user(0x27bd0000 + scc_offset, &frame->code[0]); + __put_user(0x24020000 + __NR_sigreturn, &frame->code[1]); + __put_user(0x0000000c, &frame->code[2]); /* * Flush caches so that the instructions will be correctly executed. */ - sys_cacheflush (frame->code, sizeof (frame->code), ICACHE); + flush_cache_sigtramp((unsigned long) frame->code); /* - * Set up the "normal" sigcontext_struct + * Set up the "normal" sigcontext */ - 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; + __put_user(regs->cp0_epc, &sc->sc_pc); + __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ + for(i = 31;i >= 0;i--) + __put_user(regs->regs[i], &sc->sc_regs[i]); + save_fp_context(sc); + __put_user(regs->hi, &sc->sc_mdhi); + __put_user(regs->lo, &sc->sc_mdlo); + __put_user(regs->cp0_cause, &sc->sc_cause); + __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp); + __put_user(oldmask, &sc->sc_sigset); + __put_user(0, &sc->__pad0[0]); + __put_user(0, &sc->__pad0[1]); + __put_user(0, &sc->__pad0[2]); + + regs->regs[4] = signr; /* Arguments for handler */ + regs->regs[5] = 0; /* For now. */ + regs->regs[6] = (long) frame; /* Pointer to sigcontext */ + regs->regs[29] = (unsigned long) frame; /* Stack pointer */ + regs->regs[31] = (unsigned long) frame->code; /* Return address */ + regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */ + regs->regs[25] = regs->cp0_epc; /* PIC shit... */ + return; - frame->scc.sc_t8 = regs->reg24; /* Caller saved */ - frame->scc.sc_t9 = regs->reg25; - - /* - * Don't copy k0/k1 - */ - frame->scc.sc_gp = regs->reg28; /* global pointer / s8 */ - frame->scc.sc_sp = regs->reg29; /* old stack pointer */ - frame->scc.sc_fp = regs->reg30; /* old frame pointer */ - frame->scc.sc_ra = regs->reg31; /* old return address */ +segv_and_exit: + lock_kernel(); + do_exit(SIGSEGV); + unlock_kernel(); +} - frame->scc.sc_epc = regs->cp0_epc; /* Program counter */ - frame->scc.sc_cause = regs->cp0_cause; /* c0_epc register */ +static inline void handle_signal(unsigned long signr, struct sigaction *sa, + unsigned long oldmask, struct pt_regs * regs) +{ + setup_frame(sa, regs, signr, oldmask); - frame->scc.sc_oldmask = oldmask; - *fp = frame; + if (sa->sa_flags & SA_ONESHOT) + sa->sa_handler = NULL; + if (!(sa->sa_flags & SA_NOMASK)) { + spin_lock_irq(¤t->sigmask_lock); + current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + spin_unlock_irq(¤t->sigmask_lock); + } +} - regs->reg4 = signr; /* argument for handler */ +static inline void syscall_restart(unsigned long r0, unsigned long or2, + unsigned long or7, struct pt_regs *regs, + struct sigaction *sa) +{ + switch(r0) { + case ERESTARTNOHAND: + no_system_call_restart: + regs->regs[0] = regs->regs[2] = EINTR; + break; + case ERESTARTSYS: + if(!(sa->sa_flags & SA_RESTART)) + goto no_system_call_restart; + /* fallthrough */ + case ERESTARTNOINTR: + regs->regs[0] = regs->regs[2] = or2; + regs->regs[7] = or7; + regs->cp0_epc -= 8; + } } +extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs); + /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by @@ -253,16 +261,15 @@ */ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) { - unsigned long mask; - unsigned long handler_signal = 0; - struct sc *frame = NULL; - unsigned long pc = 0; - unsigned long signr; + unsigned long mask = ~current->blocked; + unsigned long signr, r0 = regs->regs[0]; + unsigned long r7 = regs->orig_reg7; struct sigaction * sa; - int ret; - lock_kernel(); - mask = ~current->blocked; +#ifdef CONFIG_BINFMT_IRIX + if(current->personality != PER_LINUX) + return do_irix_signal(oldmask, regs); +#endif while ((signr = current->signal & mask)) { signr = ffz(~signr); clear_bit(signr, ¤t->signal); @@ -279,7 +286,9 @@ if (signr == SIGSTOP) continue; if (_S(signr) & current->blocked) { + spin_lock_irq(¤t->sigmask_lock); current->signal |= _S(signr); + spin_unlock_irq(¤t->sigmask_lock); continue; } sa = current->sig->action + signr - 1; @@ -288,7 +297,7 @@ if (signr != SIGCHLD) continue; /* check for SIGCHLD: it's special */ - while (sys_waitpid(-1,NULL,WNOHANG) > 0) + while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) /* nothing */; continue; } @@ -299,7 +308,10 @@ case SIGCONT: case SIGCHLD: case SIGWINCH: continue; - case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + case SIGSTOP: if (current->flags & PF_PTRACED) continue; current->state = TASK_STOPPED; @@ -311,68 +323,58 @@ continue; case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS: + case SIGABRT: case SIGFPE: case SIGSEGV: + case SIGBUS: + lock_kernel(); if (current->binfmt && current->binfmt->core_dump) { if (current->binfmt->core_dump(signr, regs)) signr |= 0x80; } + unlock_kernel(); /* fall through */ default: + spin_lock_irq(¤t->sigmask_lock); current->signal |= _S(signr & 0x7f); + spin_unlock_irq(¤t->sigmask_lock); + current->flags |= PF_SIGNALED; + + lock_kernel(); /* 8-( */ do_exit(signr); + unlock_kernel(); } } /* * OK, we're invoking a handler */ - if (regs->orig_reg2 >= 0) { - if (regs->reg2 == -ERESTARTNOHAND || - (regs->reg2 == -ERESTARTSYS && - !(sa->sa_flags & SA_RESTART))) - regs->reg2 = -EINTR; - } - handler_signal |= 1 << (signr-1); - mask &= ~sa->sa_mask; + if(r0) + syscall_restart(r0, regs->orig_reg2, + r7, regs, sa); + handle_signal(signr, sa, oldmask, regs); + return 1; } /* * 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 = regs->orig_reg2; + if (r0 && + (regs->regs[2] == ERESTARTNOHAND || + regs->regs[2] == ERESTARTSYS || + regs->regs[2] == ERESTARTNOINTR)) { + regs->regs[0] = regs->regs[2] = regs->orig_reg2; + regs->regs[7] = r7; regs->cp0_epc -= 8; } - ret = 0; - if (!handler_signal) /* no handler will be called - return 0 */ - goto out; - pc = regs->cp0_epc; - frame = (struct sc *) regs->reg29; - signr = 1; - 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); - pc = (unsigned long) sa->sa_handler; - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - current->blocked |= sa->sa_mask; - oldmask |= sa->sa_mask; - } - 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 0; +} - ret = 1; -out: - unlock_kernel(); - return ret; +/* + * The signal(2) syscall is no longer available in the kernel + * because GNU libc doesn't use it. Maybe I'll add it back to the + * kernel for the binary compatibility stuff. + */ +asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler) +{ + return -ENOSYS; } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.1.43/linux/arch/mips/kernel/syscall.c Sun Jan 26 02:07:05 1997 +++ linux/arch/mips/kernel/syscall.c Thu Jun 26 12:33:37 1997 @@ -5,8 +5,16 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996 by Ralf Baechle + * + * TODO: Implement the compatibility syscalls. + * Don't waste that much memory for empty entries in the syscall + * table. */ +#undef CONF_PRINT_SYSCALLS +#undef CONF_DEBUG_IRIX + +#include #include #include #include @@ -14,73 +22,79 @@ #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 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; + int error, res; lock_kernel(); error = do_pipe(fd); - if (error) + if (error) { + res = error; goto out; - regs->reg2 = fd[0]; - regs->reg3 = fd[1]; + } + regs->regs[3] = fd[1]; + res = fd[0]; out: unlock_kernel(); - return error; + return res; } asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot, int flags, int fd, off_t offset) { struct file * file = NULL; - int ret = -EBADF; + unsigned long res; lock_kernel(); - if (flags & MAP_RENAME) { + if (!(flags & MAP_ANONYMOUS)) { if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - goto out; + return -EBADF; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - ret = do_mmap(file, addr, len, prot, flags, offset); -out: + res = do_mmap(file, addr, len, prot, flags, offset); + unlock_kernel(); - return ret; + return res; } asmlinkage int sys_idle(void) { - int ret = -EPERM; + int ret = -EPERM; lock_kernel(); if (current->pid != 0) goto out; - /* endless idle loop with no priority at all */ + current->priority = -100; current->counter = -100; for (;;) { /* - * R4[26]00 have wait, R4[04]00 don't. + * R4[236]00 have wait, R4[04]00 don't. + * FIXME: We should save power by reducing the clock where + * possible. Should help alot for battery powered + * R4200/4300i systems. */ if (wait_available && !need_resched) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0\n\t"); + run_task_queue(&tq_scheduler); schedule(); } - ret = 0; out: unlock_kernel(); return ret; @@ -88,28 +102,28 @@ asmlinkage int sys_fork(struct pt_regs *regs) { - int ret; + int res; lock_kernel(); - ret = do_fork(SIGCHLD, regs->reg29, regs); + res = do_fork(SIGCHLD, regs->regs[29], regs); unlock_kernel(); - return ret; + return res; } asmlinkage int sys_clone(struct pt_regs *regs) { unsigned long clone_flags; unsigned long newsp; - int ret; + int res; lock_kernel(); - clone_flags = regs->reg4; - newsp = regs->reg5; + clone_flags = regs->regs[4]; + newsp = regs->regs[5]; if (!newsp) - newsp = regs->reg29; - ret = do_fork(clone_flags, newsp, regs); + newsp = regs->regs[29]; + res = do_fork(clone_flags, newsp, regs); unlock_kernel(); - return ret; + return res; } /* @@ -117,72 +131,136 @@ */ asmlinkage int sys_execve(struct pt_regs *regs) { - int error; + int res; char * filename; lock_kernel(); - error = getname((char *) regs->reg4, &filename); - if (error) + res = getname((char *) (long)regs->regs[4], &filename); + if (res) goto out; - error = do_execve(filename, (char **) regs->reg5, - (char **) regs->reg6, regs); + res = do_execve(filename, (char **) (long)regs->regs[5], + (char **) (long)regs->regs[6], regs); putname(filename); + out: unlock_kernel(); - return error; + return res; } /* * Do the indirect syscall syscall. + * Don't care about kernel locking; the actual syscall will do it. */ -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) +asmlinkage int sys_syscall(struct pt_regs *regs) { syscall_t syscall; + unsigned long syscallnr = regs->regs[4]; + unsigned long a0, a1, a2, a3, a4, a5, a6; + int nargs, errno; - if (a0 > __NR_Linux + __NR_Linux_syscalls) + if (syscallnr > __NR_Linux + __NR_Linux_syscalls) return -ENOSYS; - syscall = sys_call_table[a0]; + syscall = sys_call_table[syscallnr]; + nargs = sys_narg_table[syscallnr]; /* * Prevent stack overflow by recursive * syscall(__NR_syscall, __NR_syscall,...); */ - if (syscall == (syscall_t) sys_syscall) + if (syscall == (syscall_t) sys_syscall) { return -EINVAL; + } - if (syscall == NULL) + if (syscall == NULL) { return -ENOSYS; + } + if(nargs > 3) { + unsigned long usp = regs->regs[29]; + unsigned long *sp = (unsigned long *) usp; + if(usp & 3) { + printk("unaligned usp -EFAULT\n"); + force_sig(SIGSEGV, current); + return -EFAULT; + } + errno = verify_area(VERIFY_READ, (void *) (usp + 16), + (nargs - 3) * sizeof(unsigned long)); + if(errno) { + return -EFAULT; + } + switch(nargs) { + case 7: + a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = sp[7]; + break; + case 6: + a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = 0; + break; + case 5: + a3 = sp[4]; a4 = sp[5]; a5 = a6 = 0; + break; + case 4: + a3 = sp[4]; a4 = a5 = a6 = 0; + break; + + default: + a3 = a4 = a5 = a6 = 0; + break; + } + } else { + a3 = a4 = a5 = a6 = 0; + } + a0 = regs->regs[5]; a1 = regs->regs[6]; a2 = regs->regs[7]; + if(nargs == 0) + a0 = (unsigned long) regs; return syscall((void *)a0, a1, a2, a3, a4, a5, a6); } +/* + * If we ever come here the user sp is bad. Zap the process right away. + * Due to the bad stack signaling wouldn't work. + * XXX kernel locking??? + */ +asmlinkage void bad_stack(void) +{ + do_exit(SIGSEGV); +} + +#ifdef CONF_PRINT_SYSCALLS +#define SYS(fun, narg) #fun, +static char *sfnames[] = { +#include "syscalls.h" +}; +#endif + +#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX) +#define SYS(fun, narg) #fun, +static char *irix_sys_names[] = { +#include "irix5sys.h" +}; +#endif + +/* + * This isn't entirely correct with respect to kernel locking ... + */ 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) - { + /* Skip syscall instruction */ + if (delay_slot(regs)) { /* - * 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. + * By convention "li v0," is always preceeding + * the syscall instruction. So if we're in a delay slot + * userland is screwed up. */ - 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); + force_sig(SIGILL, current); return; } regs->cp0_epc += 4; - syscallnr = regs->reg2; + syscallnr = regs->regs[2]; if (syscallnr > (__NR_Linux + __NR_Linux_syscalls)) goto illegal_syscall; @@ -191,37 +269,64 @@ goto illegal_syscall; narg = sys_narg_table[syscallnr]; - if (narg > 4) - { +#ifdef CONF_PRINT_SYSCALLS + if(syscallnr >= 4000) + printk("do_sys(%s:%d): %s(%08lx,%08lx,%08lx,%08lx)", + current->comm, current->pid, sfnames[syscallnr - __NR_Linux], + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7], + regs->cp0_epc); +#endif +#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX) + if(syscallnr < 2000 && syscallnr >= 1000) { + printk("irix_sys(%s:%d): %s(", current->comm, + current->pid, irix_sys_names[syscallnr - 1000]); + if((narg < 4) && (narg != 0)) { + int i = 0; + + while(i < (narg - 1)) { + printk("%08lx, ", regs->regs[i + 4]); + i++; + } + printk("%08lx) ", regs->regs[i + 4]); + } else if(narg == 0) { + printk("%08lx, %08lx, %08lx, %08lx) ", + regs->regs[4], regs->regs[5], regs->regs[6], + regs->regs[7]); + } else + printk("narg=%d) ", narg); + } +#endif + if (narg > 4) { /* * Verify that we can safely 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) - { + usp = regs->regs[29]; + if (usp & 3) { printk("unaligned usp\n"); - send_sig(SIGSEGV, current, 1); - regs->reg2 = EFAULT; - regs->reg7 = 1; + force_sig(SIGSEGV, current); + regs->regs[2] = EFAULT; + regs->regs[7] = 1; + return; + } + if (!access_ok(VERIFY_READ, (void *) (usp + 16), + (narg - 4) * sizeof(unsigned long))) { + regs->regs[2] = EFAULT; + regs->regs[7] = 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) + if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) { goto bad_syscall; - - regs->reg2 = errno; - regs->reg7 = 0; + } + regs->regs[2] = errno; + regs->regs[7] = 0; } else { @@ -230,25 +335,49 @@ errno = do_syscalls(regs, syscall, narg); if (errno < 0 || current->errno) { - regs->reg2 = -errno; - regs->reg7 = 1; + regs->regs[2] = -errno; + regs->regs[7] = 1; } else { - regs->reg2 = errno; - regs->reg7 = 0; + regs->regs[2] = errno; + regs->regs[7] = 0; } syscall_trace(); } +#if defined(CONF_PRINT_SYSCALLS) || \ + (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) +#if 0 + printk(" returning: normal\n"); +#else + if(syscallnr >= 4000 && syscallnr < 5000) + printk(" returning: %08lx\n", (unsigned long) errno); +#endif +#endif return; bad_syscall: - regs->reg2 = -errno; - regs->reg7 = 1; + regs->regs[0] = regs->regs[2] = -errno; + regs->regs[7] = 1; +#if defined(CONF_PRINT_SYSCALLS) || \ + (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) +#if 0 + printk(" returning: bad_syscall\n"); +#else + if(syscallnr >= 4000 && syscallnr < 5000) + printk(" returning error: %d\n", errno); +#endif +#endif return; illegal_syscall: - regs->reg2 = ENOSYS; - regs->reg7 = 1; + + regs->regs[2] = ENOSYS; + regs->regs[7] = 1; +#if defined(CONF_PRINT_SYSCALLS) || \ + (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) + if(syscallnr >= 1000 && syscallnr < 2000) + printk(" returning: illegal_syscall\n"); +#endif return; } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.1.43/linux/arch/mips/kernel/syscalls.h Tue May 13 22:41:02 1997 +++ linux/arch/mips/kernel/syscalls.h Thu Jun 26 12:33:37 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996 by Ralf Baechle */ /* @@ -16,7 +16,7 @@ * * The binary compatibility calls are still missing in this list. */ -SYS(sys_syscall, 7) /* 4000 */ +SYS(sys_syscall, 0) /* 4000 */ SYS(sys_exit, 1) SYS(sys_fork, 0) SYS(sys_read, 3) @@ -88,7 +88,7 @@ SYS(sys_ssetmask, 1) SYS(sys_setreuid, 2) /* 4070 */ SYS(sys_setregid, 2) -SYS(sys_sigsuspend, 3) +SYS(sys_sigsuspend, 0) SYS(sys_sigpending, 1) SYS(sys_sethostname, 2) SYS(sys_setrlimit, 2) /* 4075 */ @@ -166,12 +166,44 @@ SYS(sys_cacheflush, 3) SYS(sys_cachectl, 3) SYS(sys_sysmips, 4) -SYS(sys_setup, 0) /* 4150 */ +SYS(sys_setup, 1) /* 4150 */ SYS(sys_getsid, 1) -SYS(sys_ni_syscall, 0) -SYS(sys_ni_syscall, 0) +SYS(sys_fdatasync, 0) +SYS(sys_sysctl, 1) SYS(sys_mlock, 2) SYS(sys_munlock, 2) /* 4155 */ SYS(sys_mlockall, 1) SYS(sys_munlockall, 0) +SYS(sys_nfsservctl, 3) +SYS(sys_sched_setparam,2) +SYS(sys_sched_getparam,2) +SYS(sys_sched_setscheduler,3) /* 4160 */ +SYS(sys_sched_getscheduler,1) +SYS(sys_sched_yield,0) +SYS(sys_sched_get_priority_max,1) +SYS(sys_sched_get_priority_min,1) +SYS(sys_sched_rr_get_interval,2) /* 4165 */ +SYS(sys_nanosleep,2) +SYS(sys_mremap,4) +SYS(sys_accept, 3) +SYS(sys_bind, 3) +SYS(sys_connect, 3) /* 4170 */ +SYS(sys_getpeername, 3) +SYS(sys_getsockname, 3) +SYS(sys_getsockopt, 5) +SYS(sys_listen, 2) +SYS(sys_recv, 4) /* 4175 */ +SYS(sys_recvfrom, 6) +SYS(sys_recvmsg, 3) +SYS(sys_send, 4) +SYS(sys_sendmsg, 3) +SYS(sys_sendto, 6) /* 4180 */ +SYS(sys_setsockopt, 5) +SYS(sys_shutdown, 2) +SYS(sys_socket, 3) +SYS(sys_socketpair, 4) +SYS(sys_setresuid, 3) /* 4185 */ +SYS(sys_getresuid, 3) +SYS(sys_query_module, 5) +SYS(sys_poll, 3) SYS(sys_nfsservctl, 3) diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.1.43/linux/arch/mips/kernel/sysirix.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/sysirix.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,2310 @@ +/* $Id: sysirix.c,v 1.1 1997/06/06 09:33:25 ralf Exp $ + * sysirix.c: IRIX system call emulation. + * + * Copyright (C) 1996 David S. Miller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 2,300 lines of complete and utter shit coming up... */ + +/* The sysmp commands supported thus far. */ +#define MP_PGSIZE 14 /* Return system page size in v1. */ + +asmlinkage int irix_sysmp(struct pt_regs *regs) +{ + unsigned long cmd; + int base = 0; + int error = 0; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + cmd = regs->regs[base + 4]; + switch(cmd) { + case MP_PGSIZE: + error = PAGE_SIZE; + break; + + default: + printk("SYSMP[%s:%d]: Unsupported opcode %d\n", + current->comm, current->pid, (int)cmd); + error = -EINVAL; + break; + } + + unlock_kernel(); + return error; +} + +/* The prctl commands. */ +#define PR_MAXPROCS 1 /* Tasks/user. */ +#define PR_ISBLOCKED 2 /* If blocked, return 1. */ +#define PR_SETSTACKSIZE 3 /* Set largest task stack size. */ +#define PR_GETSTACKSIZE 4 /* Get largest task stack size. */ +#define PR_MAXPPROCS 5 /* Num parallel tasks. */ +#define PR_UNBLKONEXEC 6 /* When task exec/exit's, unblock. */ +#define PR_SETEXITSIG 8 /* When task exit's, set signal. */ +#define PR_RESIDENT 9 /* Make task unswappable. */ +#define PR_ATTACHADDR 10 /* (Re-)Connect a vma to a task. */ +#define PR_DETACHADDR 11 /* Disconnect a vma from a task. */ +#define PR_TERMCHILD 12 /* When parent sleeps with fishes, kill child. */ +#define PR_GETSHMASK 13 /* Get the sproc() share mask. */ +#define PR_GETNSHARE 14 /* Number of share group members. */ +#define PR_COREPID 15 /* Add task pid to name when it core. */ +#define PR_ATTACHADDRPERM 16 /* (Re-)Connect vma, with specified prot. */ +#define PR_PTHREADEXIT 17 /* Kill a pthread without prejudice. */ + +asmlinkage int irix_prctl(struct pt_regs *regs) +{ + unsigned long cmd; + int error = 0, base = 0; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + cmd = regs->regs[base + 4]; + switch(cmd) { + case PR_MAXPROCS: + printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + current->comm, current->pid); + error = NR_TASKS; + break; + + case PR_ISBLOCKED: { + struct task_struct *task; + + printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n", + current->comm, current->pid); + task = find_task_by_pid(regs->regs[base + 5]); + if(!task) { + error = -ESRCH; + break; + } + error = (task->next_run ? 0 : 1); + /* Can _your_ OS find this out that fast? */ + break; + } + + case PR_SETSTACKSIZE: { + long value = regs->regs[base + 5]; + + printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n", + current->comm, current->pid, (unsigned long) value); + if(value > RLIM_INFINITY) + value = RLIM_INFINITY; + if(suser()) { + current->rlim[RLIMIT_STACK].rlim_max = + current->rlim[RLIMIT_STACK].rlim_cur = value; + error = value; + break; + } + if(value > current->rlim[RLIMIT_STACK].rlim_max) { + error = -EINVAL; + break; + } + current->rlim[RLIMIT_STACK].rlim_cur = value; + error = value; + break; + } + + case PR_GETSTACKSIZE: + printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n", + current->comm, current->pid); + error = current->rlim[RLIMIT_STACK].rlim_cur; + break; + + case PR_MAXPPROCS: + printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + current->comm, current->pid); + error = 1; + break; + + case PR_UNBLKONEXEC: + printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_SETEXITSIG: + printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n", + current->comm, current->pid); + + /* We can probably play some game where we set the task + * exit_code to some non-zero value when this is requested, + * and check whether exit_code is already set in do_exit(). + */ + error = -EINVAL; + break; + + case PR_RESIDENT: + printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n", + current->comm, current->pid); + error = 0; /* Compatability indeed. */ + break; + + case PR_ATTACHADDR: + printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_DETACHADDR: + printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_TERMCHILD: + printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_GETSHMASK: + printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n", + current->comm, current->pid); + error = -EINVAL; /* Until I have the sproc() stuff in. */ + break; + + case PR_GETNSHARE: + error = 0; /* Until I have the sproc() stuff in. */ + break; + + case PR_COREPID: + printk("irix_prctl[%s:%d]: Wants PR_COREPID\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_ATTACHADDRPERM: + printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n", + current->comm, current->pid); + error = -EINVAL; + break; + + case PR_PTHREADEXIT: + printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n", + current->comm, current->pid); + do_exit(regs->regs[base + 5]); + + default: + printk("irix_prctl[%s:%d]: Non-existant opcode %d\n", + current->comm, current->pid, (int)cmd); + error = -EINVAL; + break; + } + + unlock_kernel(); + return error; +} + +#undef DEBUG_PROCGRPS + +extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt); +extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid); +extern void sys_sync(void); +extern asmlinkage int sys_getsid(pid_t pid); +extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); +extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); +extern int getrusage(struct task_struct *p, int who, struct rusage *ru); + +/* The syssgi commands supported thus far. */ +#define SGI_SYSID 1 /* Return unique per-machine identifier. */ +#define SGI_RDNAME 6 /* Return string name of a process. */ +#define SGI_SETPGID 21 /* Set process group id. */ +#define SGI_SYSCONF 22 /* POSIX sysconf garbage. */ +#define SGI_SETGROUPS 40 /* POSIX sysconf garbage. */ +#define SGI_GETGROUPS 41 /* POSIX sysconf garbage. */ +#define SGI_RUSAGE 56 /* BSD style rusage(). */ +#define SGI_SSYNC 62 /* Synchronous fs sync. */ +#define SGI_GETSID 65 /* SysVr4 get session id. */ +#define SGI_ELFMAP 68 /* Map an elf image. */ +#define SGI_TOSSTSAVE 108 /* Toss saved vma's. */ +#define SGI_FP_BCOPY 129 /* Should FPU bcopy be used on this machine? */ +#define SGI_PHYSP 1011 /* Translate virtual into physical page. */ + +asmlinkage int irix_syssgi(struct pt_regs *regs) +{ + unsigned long cmd; + int retval, base = 0; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + + cmd = regs->regs[base + 4]; + switch(cmd) { + case SGI_SYSID: { + char *buf = (char *) regs->regs[base + 5]; + + /* XXX Use ethernet addr.... */ + retval = clear_user(buf, 64); + break; + } + + case SGI_RDNAME: { + int pid = (int) regs->regs[base + 5]; + char *buf = (char *) regs->regs[base + 6]; + struct task_struct *p; + + retval = verify_area(VERIFY_WRITE, buf, 16); + if(retval) + break; + for_each_task(p) { + if(p->pid == pid) + goto found0; + } + retval = -ESRCH; + + found0: + copy_to_user(buf, p->comm, 16); + retval = 0; + } + + case SGI_SETPGID: { +#ifdef DEBUG_PROCGRPS + printk("[%s:%d] setpgid(%d, %d) ", + current->comm, current->pid, + (int) regs->regs[base + 5], (int)regs->regs[base + 6]); +#endif + retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]); + +#ifdef DEBUG_PROCGRPS + printk("retval=%d\n", retval); +#endif + } + + case SGI_SYSCONF: { + switch(regs->regs[base + 5]) { + case 1: + retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */ + goto out; + case 2: + retval = NR_TASKS; + goto out; + case 3: + retval = HZ; + goto out; + case 4: + retval = NGROUPS; + goto out; + case 5: + retval = NR_OPEN; + goto out; + case 6: + retval = 1; + goto out; + case 7: + retval = 1; + goto out; + case 8: + retval = 199009; + goto out; + case 11: + retval = PAGE_SIZE; + goto out; + case 12: + retval = 4; + goto out; + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + retval = 0; + goto out; + case 31: + retval = 32; + goto out; + default: + retval = -EINVAL; + goto out; + }; + } + + case SGI_SETGROUPS: + retval = sys_setgroups((int) regs->regs[base + 5], + (gid_t *) regs->regs[base + 6]); + break; + + case SGI_GETGROUPS: + retval = sys_getgroups((int) regs->regs[base + 5], + (gid_t *) regs->regs[base + 6]); + break; + + case SGI_RUSAGE: { + struct rusage *ru = (struct rusage *) regs->regs[base + 6]; + + switch((int) regs->regs[base + 5]) { + case 0: + /* rusage self */ + retval = getrusage(current, RUSAGE_SELF, ru); + goto out; + + case -1: + /* rusage children */ + retval = getrusage(current, RUSAGE_CHILDREN, ru); + goto out; + + default: + retval = -EINVAL; + goto out; + }; + } + + case SGI_SSYNC: + sys_sync(); + retval = 0; + break; + + case SGI_GETSID: +#ifdef DEBUG_PROCGRPS + printk("[%s:%d] getsid(%d) ", current->comm, current->pid, + (int) regs->regs[base + 5]); +#endif + retval = sys_getsid(regs->regs[base + 5]); +#ifdef DEBUG_PROCGRPS + printk("retval=%d\n", retval); +#endif + break; + + case SGI_ELFMAP: + retval = irix_mapelf((int) regs->regs[base + 5], + (struct elf_phdr *) regs->regs[base + 6], + (int) regs->regs[base + 7]); + break; + + case SGI_TOSSTSAVE: + /* XXX We don't need to do anything? */ + retval = 0; + break; + + case SGI_FP_BCOPY: + retval = 0; + break; + + case SGI_PHYSP: { + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + unsigned long addr = regs->regs[base + 5]; + int *pageno = (int *) (regs->regs[base + 6]); + + retval = verify_area(VERIFY_WRITE, pageno, sizeof(int)); + if(retval) + return retval; + pgdp = pgd_offset(current->mm, addr); + pmdp = pmd_offset(pgdp, addr); + ptep = pte_offset(pmdp, addr); + if(ptep) { + if(pte_val(*ptep) & (_PAGE_VALID | _PAGE_PRESENT)) { + return put_user((pte_val(*ptep) & PAGE_MASK)>>PAGE_SHIFT, pageno); + return 0; + } + } + retval = -EINVAL; + break; + } + + default: + printk("irix_syssgi: Unsupported command %d\n", (int)cmd); + retval = -EINVAL; + break; + }; + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_gtime(struct pt_regs *regs) +{ + return CURRENT_TIME; +} + +int vm_enough_memory(long pages); + +/* + * IRIX is completely broken... it returns 0 on success, otherwise + * ENOMEM. + */ +asmlinkage int irix_brk(unsigned long brk) +{ + unsigned long rlim; + unsigned long newbrk, oldbrk; + struct mm_struct *mm = current->mm; + int ret; + + lock_kernel(); + if (brk < current->mm->end_code) { + ret = -ENOMEM; + goto out; + } + + newbrk = PAGE_ALIGN(brk); + oldbrk = PAGE_ALIGN(mm->brk); + if (oldbrk == newbrk) { + mm->brk = brk; + ret = 0; + goto out; + } + + /* + * Always allow shrinking brk + */ + if (brk <= current->mm->brk) { + mm->brk = brk; + do_munmap(newbrk, oldbrk-newbrk); + ret = 0; + goto out; + } + /* + * Check against rlimit and stack.. + */ + rlim = current->rlim[RLIMIT_DATA].rlim_cur; + if (rlim >= RLIM_INFINITY) + rlim = ~0; + if (brk - mm->end_code > rlim) { + ret = -ENOMEM; + goto out; + } + + /* + * Check against existing mmap mappings. + */ + if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) { + return -ENOMEM; + goto out; + } + + /* + * Check if we have enough memory.. + */ + if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) { + return -ENOMEM; + goto out; + } + + /* + * Ok, looks good - let it rip. + */ + mm->brk = brk; + do_mmap(NULL, oldbrk, newbrk-oldbrk, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + + ret = 0; + +out: + unlock_kernel(); + return ret; +} + +asmlinkage int irix_getpid(struct pt_regs *regs) +{ + regs->regs[3] = current->p_opptr->pid; + return current->pid; +} + +asmlinkage int irix_getuid(struct pt_regs *regs) +{ + regs->regs[3] = current->euid; + return current->uid; +} + +asmlinkage int irix_getgid(struct pt_regs *regs) +{ + regs->regs[3] = current->egid; + return current->gid; +} + +asmlinkage int irix_stime(int value) +{ + int ret; + + lock_kernel(); + if(!suser()) { + ret = -EPERM; + goto out; + } + cli(); + xtime.tv_sec = value; + xtime.tv_usec = 0; + time_state = TIME_ERROR; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + sti(); + ret = 0; + +out: + unlock_kernel(); + return ret; +} + +extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue); + +static inline void jiffiestotv(unsigned long jiffies, struct timeval *value) +{ + value->tv_usec = (jiffies % HZ) * (1000000 / HZ); + value->tv_sec = jiffies / HZ; + return; +} + +static inline void getitimer_real(struct itimerval *value) +{ + register unsigned long val, interval; + + interval = current->it_real_incr; + val = 0; + if (del_timer(¤t->real_timer)) { + unsigned long now = jiffies; + val = current->real_timer.expires; + add_timer(¤t->real_timer); + /* look out for negative/zero itimer.. */ + if (val <= now) + val = now+1; + val -= now; + } + jiffiestotv(val, &value->it_value); + jiffiestotv(interval, &value->it_interval); +} + +asmlinkage unsigned int irix_alarm(unsigned int seconds) +{ + struct itimerval it_new, it_old; + unsigned int oldalarm; + + lock_kernel(); + if(!seconds) { + getitimer_real(&it_old); + del_timer(¤t->real_timer); + } else { + it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; + it_new.it_value.tv_sec = seconds; + it_new.it_value.tv_usec = 0; + _setitimer(ITIMER_REAL, &it_new, &it_old); + } + oldalarm = it_old.it_value.tv_sec; + /* ehhh.. We can't return 0 if we have an alarm pending.. */ + /* And we'd better return too much than too little anyway */ + if (it_old.it_value.tv_usec) + oldalarm++; + unlock_kernel(); + return oldalarm; +} + +asmlinkage int irix_pause(void) +{ + lock_kernel(); + current->state = TASK_INTERRUPTIBLE; + schedule(); + unlock_kernel(); + return -EINTR; +} + +extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void * data); + +/* XXX need more than this... */ +asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags, + char *type, void *data, int datalen) +{ + int ret; + + lock_kernel(); + printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", + current->comm, current->pid, + dev_name, dir_name, flags, type, data, datalen); + ret = sys_mount(dev_name, dir_name, type, flags, data); + + unlock_kernel(); + return ret; +} + +struct irix_statfs { + short f_type; + long f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree; + char f_fname[6], f_fpack[6]; +}; + +asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, + int len, int fs_type) +{ + struct inode *inode; + struct statfs kbuf; + int error, old_fs, i; + + /* We don't support this feature yet. */ + if(fs_type) { + error = -EINVAL; + goto out; + } + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); + if (error) + goto out; + error = namei(path,&inode); + if (error) + goto out; + if (!inode->i_sb->s_op->statfs) { + iput(inode); + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + iput(inode); + __put_user(kbuf.f_type, &buf->f_type); + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + for(i = 0; i < 6; i++) { + __put_user(0, &buf->f_fname[i]); + __put_user(0, &buf->f_fpack[i]); + } + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) +{ + struct inode * inode; + struct statfs kbuf; + struct file *file; + int error, old_fs, i; + + lock_kernel(); + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); + if (error) + goto out; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!(inode = file->f_inode)) { + error = -ENOENT; + goto out; + } + if (!inode->i_sb->s_op->statfs) { + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + __put_user(kbuf.f_type, &buf->f_type); + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + for(i = 0; i < 6; i++) { + __put_user(0, &buf->f_fname[i]); + __put_user(0, &buf->f_fpack[i]); + } + error = 0; + +out: + unlock_kernel(); + return error; +} + +extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid); +extern asmlinkage int sys_setsid(void); + +asmlinkage int irix_setpgrp(int flags) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_PROCGRPS + printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); +#endif + if(!flags) + error = current->pgrp; + else + error = sys_setsid(); +#ifdef DEBUG_PROCGRPS + printk("returning %d\n", current->pgrp); +#endif + + unlock_kernel(); + return error; +} + +asmlinkage int irix_times(struct tms * tbuf) +{ + int error; + + lock_kernel(); + if (tbuf) { + error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf); + if (error) + goto out; + __put_user(current->times.tms_utime,&tbuf->tms_utime); + __put_user(current->times.tms_stime,&tbuf->tms_stime); + __put_user(current->times.tms_cutime,&tbuf->tms_cutime); + __put_user(current->times.tms_cstime,&tbuf->tms_cstime); + } + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_exec(struct pt_regs *regs) +{ + int error, base = 0; + char * filename; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + error = getname((char *) (long)regs->regs[base + 4], &filename); + if (error) + goto out; + error = do_execve(filename, (char **) (long)regs->regs[base + 5], + (char **) 0, regs); + putname(filename); + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_exece(struct pt_regs *regs) +{ + int error, base = 0; + char * filename; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + error = getname((char *) (long)regs->regs[base + 4], &filename); + if (error) + goto out; + error = do_execve(filename, (char **) (long)regs->regs[base + 5], + (char **) (long)regs->regs[base + 6], regs); + putname(filename); + +out: + unlock_kernel(); + return error; +} + +asmlinkage unsigned long irix_gethostid(void) +{ + lock_kernel(); + printk("[%s:%d]: irix_gethostid() called...\n", + current->comm, current->pid); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage unsigned long irix_sethostid(unsigned long val) +{ + lock_kernel(); + printk("[%s:%d]: irix_sethostid(%08lx) called...\n", + current->comm, current->pid, val); + unlock_kernel(); + return -EINVAL; +} + +extern asmlinkage int sys_socket(int family, int type, int protocol); + +asmlinkage int irix_socket(int family, int type, int protocol) +{ + switch(type) { + case 1: + type = SOCK_DGRAM; + break; + + case 2: + type = SOCK_STREAM; + break; + + case 3: + type = 9; /* Invalid... */ + break; + + case 4: + type = SOCK_RAW; + break; + + case 5: + type = SOCK_RDM; + break; + + case 6: + type = SOCK_SEQPACKET; + break; + + default: + break; + } + + return sys_socket(family, type, protocol); +} + +asmlinkage int irix_getdomainname(char *name, int len) +{ + int error; + + lock_kernel(); + if(len > (__NEW_UTS_LEN - 1)) + len = __NEW_UTS_LEN - 1; + error = verify_area(VERIFY_WRITE, name, len); + if(error) + goto out; + if(copy_to_user(name, system_utsname.domainname, len)) { + error = -EFAULT; + goto out; + } + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage unsigned long irix_getpagesize(void) +{ + return PAGE_SIZE; +} + +asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4) +{ + switch(opcode) { + case 0: + return sys_msgget((key_t) arg0, (int) arg1); + case 1: + return sys_msgctl((int) arg0, (int) arg1, (struct msqid_ds *)arg2); + case 2: + return sys_msgrcv((int) arg0, (struct msgbuf *) arg1, + (size_t) arg2, (long) arg3, (int) arg4); + case 3: + return sys_msgsnd((int) arg0, (struct msgbuf *) arg1, + (size_t) arg2, (int) arg3); + default: + return -EINVAL; + } +} + +asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3) +{ + switch(opcode) { + case 0: + return sys_shmat((int) arg0, (char *)arg1, (int) arg2, + (unsigned long *) arg3); + case 1: + return sys_shmctl((int)arg0, (int)arg1, (struct shmid_ds *)arg2); + case 2: + return sys_shmdt((char *)arg0); + case 3: + return sys_shmget((key_t) arg0, (int) arg1, (int) arg2); + default: + return -EINVAL; + } +} + +asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1, + unsigned long arg2, int arg3) +{ + switch(opcode) { + case 0: + return sys_semctl((int) arg0, (int) arg1, (int) arg2, + (union semun) arg3); + case 1: + return sys_semget((key_t) arg0, (int) arg1, (int) arg2); + case 2: + return sys_semop((int) arg0, (struct sembuf *)arg1, + (unsigned int) arg2); + default: + return -EINVAL; + } +} + +extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, + unsigned long offset_low, loff_t * result, + unsigned int origin); + +asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base) +{ + loff_t junk; + int old_fs, error; + + lock_kernel(); + old_fs = get_fs(); set_fs(get_ds()); + error = sys_llseek(fd, offhi, offlow, &junk, base); + set_fs(old_fs); + + if(error) + goto out; + error = (int) junk; +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_sginap(int ticks) +{ + lock_kernel(); + if(ticks) { + current->timeout = ticks + jiffies; + current->state = TASK_INTERRUPTIBLE; + } + schedule(); + unlock_kernel(); + return 0; +} + +asmlinkage int irix_sgikopt(char *istring, char *ostring, int len) +{ + return -EINVAL; +} + +asmlinkage int irix_gettimeofday(struct timeval *tv) +{ + int retval; + + lock_kernel(); + retval = copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0; + unlock_kernel(); + return retval; +} + +asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, + int flags, int fd, off_t offset) +{ + struct file *file = NULL; + unsigned long retval; + + lock_kernel(); + if(!(flags & MAP_ANONYMOUS)) { + if(fd >= NR_OPEN || !(file = current->files->fd[fd])) { + retval = -EBADF; + goto out; + } + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + retval = do_mmap(file, addr, len, prot, flags, offset); + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_madvise(unsigned long addr, int len, int behavior) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n", + current->comm, current->pid, addr, len, behavior); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_pagelock(char *addr, int len, int op) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n", + current->comm, current->pid, addr, len, op); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_quotactl(struct pt_regs *regs) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_quotactl()\n", + current->comm, current->pid); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_BSDsetpgrp(int pid, int pgrp) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_PROCGRPS + printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid, + pid, pgrp); +#endif + if(!pid) + pid = current->pid; + + /* Wheee, weird sysv thing... */ + if((pgrp == 0) && (pid == current->pid)) + error = sys_setsid(); + else + error = sys_setpgid(pid, pgrp); + +#ifdef DEBUG_PROCGRPS + printk("error = %d\n", error); +#endif + + unlock_kernel(); + return error; +} + +asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n", + current->comm, current->pid, cmd, buf, cnt); + unlock_kernel(); + return -EINVAL; +} + +struct iuname { + char sysname[257], nodename[257], release[257]; + char version[257], machine[257]; + char m_type[257], base_rel[257]; + char _unused0[257], _unused1[257], _unused2[257]; + char _unused3[257], _unused4[257], _unused5[257]; +}; + +asmlinkage int irix_uname(struct iuname *buf) +{ + int retval; + + lock_kernel(); + if(copy_to_user(system_utsname.sysname, buf->sysname, 65) + || copy_to_user(system_utsname.nodename, buf->nodename, 65) + || copy_to_user(system_utsname.release, buf->release, 65) + || copy_to_user(system_utsname.version, buf->version, 65) + || copy_to_user(system_utsname.machine, buf->machine, 65)) { + retval = -EFAULT; + goto out; + } + retval = 1; + +out: + unlock_kernel(); + return retval; +} + +#undef DEBUG_XSTAT + +static inline int irix_xstat32_xlate(struct stat *kb, struct stat *ubuf) +{ + struct xstat32 { + u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid; + u32 st_rdev, st_pad2[2], st_size, st_pad3; + u32 st_atime0, st_atime1; + u32 st_mtime0, st_mtime1; + u32 st_ctime0, st_ctime1; + u32 st_blksize, st_blocks; + char st_fstype[16]; + u32 st_pad4[8]; + } *ub = (struct xstat32 *) ubuf; + + return copy_to_user(ub, kb, sizeof(*ub)) ? -EFAULT : 0; +} + +static inline void irix_xstat64_xlate(struct stat *sb) +{ + struct xstat64 { + u32 st_dev; s32 st_pad1[3]; + unsigned long long st_ino; + u32 st_mode; + u32 st_nlink; s32 st_uid; s32 st_gid; u32 st_rdev; + s32 st_pad2[2]; + long long st_size; + s32 st_pad3; + struct { s32 tv_sec, tv_nsec; } st_atime, st_mtime, st_ctime; + s32 st_blksize; + long long st_blocks; + char st_fstype[16]; + s32 st_pad4[8]; + } ks; + + ks.st_dev = (u32) sb->st_dev; + ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0; + ks.st_ino = (unsigned long long) sb->st_ino; + ks.st_mode = (u32) sb->st_mode; + ks.st_nlink = (u32) sb->st_nlink; + ks.st_uid = (s32) sb->st_uid; + ks.st_gid = (s32) sb->st_gid; + ks.st_rdev = (u32) sb->st_rdev; + ks.st_pad2[0] = ks.st_pad2[1] = 0; + ks.st_size = (long long) sb->st_size; + ks.st_pad3 = 0; + + /* XXX hackety hack... */ + ks.st_atime.tv_sec = (s32) sb->st_atime; ks.st_atime.tv_nsec = 0; + ks.st_mtime.tv_sec = (s32) sb->st_atime; ks.st_mtime.tv_nsec = 0; + ks.st_ctime.tv_sec = (s32) sb->st_atime; ks.st_ctime.tv_nsec = 0; + + ks.st_blksize = (s32) sb->st_blksize; + ks.st_blocks = (long long) sb->st_blocks; + memcpy(&ks.st_fstype[0], &sb->st_fstype[0], 16); + ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = + ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0; + + /* Now write it all back. */ + copy_to_user(sb, &ks, sizeof(struct xstat64)); +} + +extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf); + +asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf) +{ + int retval; + + lock_kernel(); +#ifdef DEBUG_XSTAT + printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ", + current->comm, current->pid, version, filename, statbuf); +#endif + switch(version) { + case 2: { + struct stat kb; + int old_fs; + + old_fs = get_fs(); set_fs(get_ds()); + retval = sys_newstat(filename, &kb); + set_fs(old_fs); +#ifdef DEBUG_XSTAT + printk("retval[%d]\n", retval); +#endif + if(retval) + goto out; + retval = irix_xstat32_xlate(&kb, statbuf); + goto out; + } + + case 3: { + retval = sys_newstat(filename, statbuf); +#ifdef DEBUG_XSTAT + printk("retval[%d]\n", retval); +#endif + if(retval) + goto out; + + irix_xstat64_xlate(statbuf); + retval = 0; + break; + } + + default: + retval = -EINVAL; + break; + } + +out: + unlock_kernel(); + return retval; +} + +extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf); + +asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_XSTAT + printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ", + current->comm, current->pid, version, filename, statbuf); +#endif + switch(version) { + case 2: { + struct stat kb; + int old_fs; + + old_fs = get_fs(); set_fs(get_ds()); + error = sys_newlstat(filename, &kb); + set_fs(old_fs); +#ifdef DEBUG_XSTAT + printk("error[%d]\n", error); +#endif + if(error) + goto out; + error = irix_xstat32_xlate(&kb, statbuf); + goto out; + } + + case 3: { + error = sys_newlstat(filename, statbuf); +#ifdef DEBUG_XSTAT + printk("error[%d]\n", error); +#endif + if(error) + goto out; + + irix_xstat64_xlate(statbuf); + error = 0; + goto out; + } + + default: + error = -EINVAL; + goto out; + } + +out: + unlock_kernel(); + return error; +} + +extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf); + +asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf) +{ + int error; + + lock_kernel(); +#ifdef DEBUG_XSTAT + printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ", + current->comm, current->pid, version, fd, statbuf); +#endif + switch(version) { + case 2: { + struct stat kb; + int old_fs; + + old_fs = get_fs(); set_fs(get_ds()); + error = sys_newfstat(fd, &kb); + set_fs(old_fs); +#ifdef DEBUG_XSTAT + printk("error[%d]\n", error); +#endif + if(error) + goto out; + error = irix_xstat32_xlate(&kb, statbuf); + goto out; + } + + case 3: { + error = sys_newfstat(fd, statbuf); +#ifdef DEBUG_XSTAT + printk("error[%d]\n", error); +#endif + if(error) + goto out; + + irix_xstat64_xlate(statbuf); + error = 0; + goto out; + } + + default: + error = -EINVAL; + goto out; + } + +out: + unlock_kernel(); + return error; +} + +extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev); + +asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev) +{ + int retval; + + lock_kernel(); + printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", + current->comm, current->pid, ver, filename, mode, (int) dev); + switch(ver) { + case 2: + retval = sys_mknod(filename, mode, dev); + goto out; + + default: + retval = -EINVAL; + goto out; + }; + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_swapctl(int cmd, char *arg) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n", + current->comm, current->pid, cmd, arg); + unlock_kernel(); + return -EINVAL; +} + +struct irix_statvfs { + u32 f_bsize; u32 f_frsize; u32 f_blocks; + u32 f_bfree; u32 f_bavail; u32 f_files; u32 f_ffree; u32 f_favail; + u32 f_fsid; char f_basetype[16]; + u32 f_flag; u32 f_namemax; + char f_fstr[32]; u32 f_filler[16]; +}; + +asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) +{ + struct inode *inode; + struct statfs kbuf; + int error, old_fs, i; + + lock_kernel(); + printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + current->comm, current->pid, fname, buf); + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); + if(error) + goto out; + error = namei(fname, &inode); + if(error) + goto out; + if(!inode->i_sb->s_op->statfs) { + iput(inode); + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + iput(inode); + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */ + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */ +#ifdef __MIPSEB__ + __put_user(kbuf.f_fsid.val[1], &buf->f_fsid); +#else + __put_user(kbuf.f_fsid.val[0], &buf->f_fsid); +#endif + for(i = 0; i < 16; i++) + __put_user(0, &buf->f_basetype[i]); + __put_user(0, &buf->f_flag); + __put_user(kbuf.f_namelen, &buf->f_namemax); + for(i = 0; i < 32; i++) + __put_user(0, &buf->f_fstr[i]); + + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) +{ + struct inode * inode; + struct statfs kbuf; + struct file *file; + int error, old_fs, i; + + lock_kernel(); + printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + current->comm, current->pid, fd, buf); + + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); + if (error) + goto out; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!(inode = file->f_inode)) { + error = -ENOENT; + goto out; + } + if (!inode->i_sb->s_op->statfs) { + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */ + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */ +#ifdef __MIPSEB__ + __put_user(kbuf.f_fsid.val[1], &buf->f_fsid); +#else + __put_user(kbuf.f_fsid.val[0], &buf->f_fsid); +#endif + for(i = 0; i < 16; i++) + __put_user(0, &buf->f_basetype[i]); + __put_user(0, &buf->f_flag); + __put_user(kbuf.f_namelen, &buf->f_namemax); + for(i = 0; i < 32; i++) + __put_user(0, &buf->f_fstr[i]); + + error = 0; + +out: + unlock_kernel(); + return error; +} + +#define NOFOLLOW_LINKS 0 +#define FOLLOW_LINKS 1 + +static inline int chown_common(char *filename, uid_t user, gid_t group, int follow) +{ + struct inode * inode; + int error; + struct iattr newattrs; + + if(follow == NOFOLLOW_LINKS) + error = lnamei(filename,&inode); + else + error = namei(filename,&inode); + if (error) + return error; + if (IS_RDONLY(inode)) { + iput(inode); + return -EROFS; + } + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + iput(inode); + return -EPERM; + } + if (user == (uid_t) -1) + user = inode->i_uid; + if (group == (gid_t) -1) + group = inode->i_gid; + newattrs.ia_mode = inode->i_mode; + newattrs.ia_uid = user; + newattrs.ia_gid = group; + newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; + /* + * If the owner has been changed, remove the setuid bit + */ + if (inode->i_mode & S_ISUID) { + newattrs.ia_mode &= ~S_ISUID; + newattrs.ia_valid |= ATTR_MODE; + } + /* + * If the group has been changed, remove the setgid bit + * + * Don't remove the setgid bit if no group execute bit. + * This is a file marked for mandatory locking. + */ + if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) { + newattrs.ia_mode &= ~S_ISGID; + newattrs.ia_valid |= ATTR_MODE; + } + inode->i_dirt = 1; + 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); +} + +asmlinkage int irix_chown(char *fname, int uid, int gid) +{ + int retval; + + lock_kernel(); + /* Do follow any and all links... */ + retval = chown_common(fname, uid, gid, FOLLOW_LINKS); + unlock_kernel(); + return retval; +} + +asmlinkage int irix_lchown(char *fname, int uid, int gid) +{ + int retval; + + lock_kernel(); + /* Do _not_ follow any links... */ + retval = chown_common(fname, uid, gid, NOFOLLOW_LINKS); + unlock_kernel(); + return retval; +} + +asmlinkage int irix_priocntl(struct pt_regs *regs) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_priocntl()\n", + current->comm, current->pid); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_sigqueue(int pid, int sig, int code, int val) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", + current->comm, current->pid, pid, sig, code, val); + unlock_kernel(); + return -EINVAL; +} + +extern asmlinkage int sys_truncate(const char * path, unsigned long length); +extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length); + +asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2) +{ + int retval; + + lock_kernel(); + if(size1) { + retval = -EINVAL; + goto out; + } + retval = sys_truncate(name, size2); + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2) +{ + int retval; + + lock_kernel(); + if(size1) { + retval = -EINVAL; + goto out; + } + retval = sys_ftruncate(fd, size2); + +out: + unlock_kernel(); + return retval; +} + +extern asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot, + int flags, int fd, off_t offset); + +asmlinkage int irix_mmap64(struct pt_regs *regs) +{ + unsigned long addr, *sp; + int len, prot, flags, fd, off1, off2, base = 0; + int error; + + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + sp = (unsigned long *) (regs->regs[29] + 16); + addr = regs->regs[base + 4]; + len = regs->regs[base + 5]; + prot = regs->regs[base + 6]; + if(!base) { + flags = regs->regs[base + 7]; + error = verify_area(VERIFY_READ, sp, (4 * sizeof(unsigned long))); + if(error) + goto out; + fd = sp[0]; + __get_user(off1, &sp[1]); + __get_user(off2, &sp[2]); + } else { + error = verify_area(VERIFY_READ, sp, (5 * sizeof(unsigned long))); + if(error) + goto out; + __get_user(flags, &sp[0]); + __get_user(fd, &sp[1]); + __get_user(off1, &sp[2]); + __get_user(off2, &sp[3]); + } + if(off1) { + error = -EINVAL; + goto out; + } + error = sys_mmap(addr, (size_t) len, prot, flags, fd, off2); + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_dmi(struct pt_regs *regs) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_dmi()\n", + current->comm, current->pid); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64, + int off1, int off2) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", + current->comm, current->pid, fd, buf, cnt, off64, off1, off2); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64, + int off1, int off2) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", + current->comm, current->pid, fd, buf, cnt, off64, off1, off2); + unlock_kernel(); + return -EINVAL; +} + +asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," + "%08lx,%08lx)\n", + current->comm, current->pid, cmd, arg0, arg1, arg2, + arg3, arg4, arg5); + unlock_kernel(); + return -EINVAL; +} + +struct irix_statvfs64 { + u32 f_bsize; u32 f_frsize; + u64 f_blocks; u64 f_bfree; u64 f_bavail; + u64 f_files; u64 f_ffree; u64 f_favail; + u32 f_fsid; + char f_basetype[16]; + u32 f_flag; u32 f_namemax; + char f_fstr[32]; + u32 f_filler[16]; +}; + +asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) +{ + struct inode *inode; + struct statfs kbuf; + int error, old_fs, i; + + printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + current->comm, current->pid, fname, buf); + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); + if(error) + goto out; + error = namei(fname, &inode); + if(error) + goto out; + if(!inode->i_sb->s_op->statfs) { + iput(inode); + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + iput(inode); + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */ + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */ +#ifdef __MIPSEB__ + __put_user(kbuf.f_fsid.val[1], &buf->f_fsid); +#else + __put_user(kbuf.f_fsid.val[0], &buf->f_fsid); +#endif + for(i = 0; i < 16; i++) + __put_user(0, &buf->f_basetype[i]); + __put_user(0, &buf->f_flag); + __put_user(kbuf.f_namelen, &buf->f_namemax); + for(i = 0; i < 32; i++) + __put_user(0, &buf->f_fstr[i]); + + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) +{ + struct inode * inode; + struct statfs kbuf; + struct file *file; + int error, old_fs, i; + + lock_kernel(); + printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + current->comm, current->pid, fd, buf); + + error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); + if (error) + goto out; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!(inode = file->f_inode)) { + error = -ENOENT; + goto out; + } + if (!inode->i_sb->s_op->statfs) { + error = -ENOSYS; + goto out; + } + + old_fs = get_fs(); set_fs(get_ds()); + inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + set_fs(old_fs); + + __put_user(kbuf.f_bsize, &buf->f_bsize); + __put_user(kbuf.f_frsize, &buf->f_frsize); + __put_user(kbuf.f_blocks, &buf->f_blocks); + __put_user(kbuf.f_bfree, &buf->f_bfree); + __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */ + __put_user(kbuf.f_files, &buf->f_files); + __put_user(kbuf.f_ffree, &buf->f_ffree); + __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */ +#ifdef __MIPSEB__ + __put_user(kbuf.f_fsid.val[1], &buf->f_fsid); +#else + __put_user(kbuf.f_fsid.val[0], &buf->f_fsid); +#endif + for(i = 0; i < 16; i++) + __put_user(0, &buf->f_basetype[i]); + __put_user(0, &buf->f_flag); + __put_user(kbuf.f_namelen, &buf->f_namemax); + for(i = 0; i < 32; i++) + __put_user(0, &buf->f_fstr[i]); + + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf) +{ + int error; + + lock_kernel(); + printk("[%s:%d] irix_getmountid(%s, %p)\n", + current->comm, current->pid, fname, midbuf); + error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)); + if(error) + goto out; + + /* + * The idea with this system call is that when trying to determine + * 'pwd' and it's a toss-up for some reason, userland can use the + * fsid of the filesystem to try and make the right decision, but + * we don't have this so for now. XXX + */ + __put_user(0, &midbuf[0]); + __put_user(0, &midbuf[1]); + __put_user(0, &midbuf[2]); + __put_user(0, &midbuf[3]); + error = 0; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask, + unsigned long arg, unsigned long sp, int slen) +{ + lock_kernel(); + printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", + current->comm, current->pid, entry, mask, arg, sp, slen); + unlock_kernel(); + return -EINVAL; +} + +#undef DEBUG_GETDENTS + +struct irix_dirent32 { + u32 d_ino; + u32 d_off; + unsigned short d_reclen; + char d_name[1]; +}; + +struct irix_dirent32_callback { + struct irix_dirent32 *current_dir; + struct irix_dirent32 *previous; + int count; + int error; +}; + +#define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) + +static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offset, ino_t ino) +{ + struct irix_dirent32 *dirent; + struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf; + unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1); + int retval; + + lock_kernel(); +#ifdef DEBUG_GETDENTS + printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]", + reclen, namlen, buf->count); +#endif + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) { + retval = -EINVAL; + goto out; + } + dirent = buf->previous; + if (dirent) + __put_user(offset, &dirent->d_off); + dirent = buf->current_dir; + buf->previous = dirent; + __put_user(ino, &dirent->d_ino); + __put_user(reclen, &dirent->d_reclen); + copy_to_user(dirent->d_name, name, namlen); + __put_user(0, &dirent->d_name[namlen]); + ((char *) dirent) += reclen; + buf->current_dir = dirent; + buf->count -= reclen; + + retval = 0; + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) +{ + struct file *file; + struct irix_dirent32 *lastdirent; + struct irix_dirent32_callback buf; + int error; + + lock_kernel(); +#ifdef DEBUG_GETDENTS + printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm, + current->pid, fd, dirent, count, eob); +#endif + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!file->f_op || !file->f_op->readdir) { + error = -ENOTDIR; + goto out; + } + if(verify_area(VERIFY_WRITE, dirent, count) || + verify_area(VERIFY_WRITE, eob, sizeof(*eob))) { + error = -EFAULT; + goto out; + } + __put_user(0, eob); + buf.current_dir = (struct irix_dirent32 *) dirent; + buf.previous = NULL; + buf.count = count; + buf.error = 0; + error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir32); + if (error < 0) + goto out; + lastdirent = buf.previous; + if (!lastdirent) { + error = buf.error; + goto out; + } + lastdirent->d_off = (u32) file->f_pos; +#ifdef DEBUG_GETDENTS + printk("eob=%d returning %d\n", *eob, count - buf.count); +#endif + error = count - buf.count; + +out: + unlock_kernel(); + return error; +} + +struct irix_dirent64 { + u64 d_ino; + u64 d_off; + unsigned short d_reclen; + char d_name[1]; +}; + +struct irix_dirent64_callback { + struct irix_dirent64 *curr; + struct irix_dirent64 *previous; + int count; + int error; +}; + +#define NAME_OFFSET64(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) + +static int irix_filldir64(void * __buf, const char * name, int namlen, + off_t offset, ino_t ino) +{ + struct irix_dirent64 *dirent; + struct irix_dirent64_callback * buf = + (struct irix_dirent64_callback *) __buf; + unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1); + int retval; + + lock_kernel(); + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) { + retval = -EINVAL; + goto out; + } + dirent = buf->previous; + if (dirent) + __put_user(offset, &dirent->d_off); + dirent = buf->curr; + buf->previous = dirent; + __put_user(ino, &dirent->d_ino); + __put_user(reclen, &dirent->d_reclen); + copy_to_user(dirent->d_name, name, namlen); + __put_user(0, &dirent->d_name[namlen]); + ((char *) dirent) += reclen; + buf->curr = dirent; + buf->count -= reclen; + + retval = 0; +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) +{ + struct file *file; + struct irix_dirent64 *lastdirent; + struct irix_dirent64_callback buf; + int error; + + lock_kernel(); +#ifdef DEBUG_GETDENTS + printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm, + current->pid, fd, dirent, cnt); +#endif + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!file->f_op || !file->f_op->readdir) { + error = -ENOTDIR; + goto out; + } + if(verify_area(VERIFY_WRITE, dirent, cnt)) { + error = -EFAULT; + goto out; + } + if(cnt < (sizeof(struct irix_dirent64) + 255)) { + error = -EINVAL; + goto out; + } + + buf.curr = (struct irix_dirent64 *) dirent; + buf.previous = NULL; + buf.count = cnt; + buf.error = 0; + error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64); + if (error < 0) + goto out; + lastdirent = buf.previous; + if (!lastdirent) { + error = buf.error; + goto out; + } + lastdirent->d_off = (u64) file->f_pos; +#ifdef DEBUG_GETDENTS + printk("returning %d\n", cnt - buf.count); +#endif + error = cnt - buf.count; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) +{ + struct file *file; + struct irix_dirent64 *lastdirent; + struct irix_dirent64_callback buf; + int error; + + lock_kernel(); +#ifdef DEBUG_GETDENTS + printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm, + current->pid, fd, dirent, cnt); +#endif + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + if (!file->f_op || !file->f_op->readdir) { + error = -ENOTDIR; + goto out; + } + if(verify_area(VERIFY_WRITE, dirent, cnt) || + verify_area(VERIFY_WRITE, eob, sizeof(*eob))) { + error = -EFAULT; + goto out; + } + if(cnt < (sizeof(struct irix_dirent64) + 255)) { + error = -EINVAL; + goto out; + } + + *eob = 0; + buf.curr = (struct irix_dirent64 *) dirent; + buf.previous = NULL; + buf.count = cnt; + buf.error = 0; + error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64); + if (error < 0) + goto out; + lastdirent = buf.previous; + if (!lastdirent) { + error = buf.error; + goto out; + } + lastdirent->d_off = (u64) file->f_pos; +#ifdef DEBUG_GETDENTS + printk("eob=%d returning %d\n", *eob, cnt - buf.count); +#endif + error = cnt - buf.count; + +out: + unlock_kernel(); + return error; +} + +asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long arg) +{ + int retval; + + lock_kernel(); + switch(op) { + case 1: + /* Reboot */ + printk("[%s:%d] irix_uadmin: Wants to reboot...\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 2: + /* Shutdown */ + printk("[%s:%d] irix_uadmin: Wants to shutdown...\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 4: + /* Remount-root */ + printk("[%s:%d] irix_uadmin: Wants to remount root...\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 8: + /* Kill all tasks. */ + printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 256: + /* Set magic mushrooms... */ + printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n", + current->comm, current->pid, (int) func); + retval = -EINVAL; + goto out; + + default: + printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n", + current->comm, current->pid, (int) op); + retval = -EINVAL; + goto out; + }; + +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf) +{ + int retval; + + lock_kernel(); + switch(type) { + case 0: + /* uname() */ + retval = irix_uname((struct iuname *)inbuf); + goto out; + + case 2: + /* ustat() */ + printk("[%s:%d] irix_utssys: Wants to do ustat()\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 3: + /* fusers() */ + printk("[%s:%d] irix_utssys: Wants to do fusers()\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + default: + printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n", + current->comm, current->pid, (int) type); + retval = -EINVAL; + goto out; + } + +out: + unlock_kernel(); + return retval; +} + +#undef DEBUG_FCNTL + +extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, + unsigned long arg); + +asmlinkage int irix_fcntl(int fd, int cmd, int arg) +{ + int retval; + + lock_kernel(); +#ifdef DEBUG_FCNTL + printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm, + current->pid, fd, cmd, arg); +#endif + + retval = sys_fcntl(fd, cmd, arg); +#ifdef DEBUG_FCNTL + printk("%d\n", retval); +#endif + unlock_kernel(); + return retval; +} + +asmlinkage int irix_ulimit(int cmd, int arg) +{ + int retval; + + lock_kernel(); + switch(cmd) { + case 1: + printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 2: + printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 3: + printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + case 4: +#if 0 + printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; +#endif + retval = current->rlim[RLIMIT_NOFILE].rlim_cur; + goto out; + + case 5: + printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n", + current->comm, current->pid); + retval = -EINVAL; + goto out; + + default: + printk("[%s:%d] irix_ulimit: Unknown command [%d].\n", + current->comm, current->pid, cmd); + retval = -EINVAL; + goto out; + } +out: + unlock_kernel(); + return retval; +} + +asmlinkage int irix_unimp(struct pt_regs *regs) +{ + lock_kernel(); + printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " + "a3=%08lx\n", current->comm, current->pid, + (int) regs->regs[2], (int) regs->regs[3], + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); + unlock_kernel(); + + return -ENOSYS; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.1.43/linux/arch/mips/kernel/sysmips.c Sun Jan 26 02:07:05 1997 +++ linux/arch/mips/kernel/sysmips.c Thu Jun 26 12:33:37 1997 @@ -17,14 +17,9 @@ #include #include -#include +#include #include - -static inline size_t -strnlen_user(const char *s, size_t count) -{ - return strnlen(s, count); -} +#include /* * How long a hostname can we get from user space? @@ -37,7 +32,7 @@ { struct vm_area_struct * vma; - vma = find_vma(current, address); + vma = find_vma(current->mm, address); if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ)) return -EFAULT; address = vma->vm_end - address; @@ -54,32 +49,35 @@ { int *p; char *name; - int flags, len, retval = -EINVAL; + int flags, tmp, len, retval; lock_kernel(); switch(cmd) { case SETNAME: - retval = -EPERM; - if (!suser()) + if (!suser()) { + retval = -EPERM; goto out; + } name = (char *) arg1; - len = get_max_hostname((unsigned long)name); - retval = len; + len = strlen_user(name); if (len < 0) + retval = len; goto out; - len = strnlen_user(name, retval); - retval = -EINVAL; if (len == 0 || len > __NEW_UTS_LEN) + retval = -EINVAL; goto out; - memcpy_fromfs(system_utsname.nodename, name, len); + copy_from_user(system_utsname.nodename, name, len); system_utsname.nodename[len] = '\0'; retval = 0; goto out; + case MIPS_ATOMIC_SET: + /* This is broken in case of page faults and SMP ... + Risc/OS fauls after maximum 20 tries with EAGAIN. */ p = (int *) arg1; - retval = -EINVAL; - if(verify_area(VERIFY_WRITE, p, sizeof(*p))) + retval = verify_area(VERIFY_WRITE, p, sizeof(*p)); + if (retval) goto out; save_flags(flags); cli(); @@ -87,18 +85,27 @@ *p = arg2; restore_flags(flags); goto out; + case MIPS_FIXADE: - if (arg1) - current->tss.mflags |= MF_FIXADE; - else - current->tss.mflags |= MF_FIXADE; + tmp = current->tss.mflags & ~3; + current->tss.mflags = tmp | (arg1 & 3); retval = 0; goto out; + case FLUSH_CACHE: - sys_cacheflush(0, ~0, BCACHE); + flush_cache_all(); retval = 0; goto out; + + case MIPS_RDNVRAM: + retval = -EIO; + goto out; + + default: + retval = -EINVAL; + goto out; } + out: unlock_kernel(); return retval; diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.1.43/linux/arch/mips/kernel/time.c Mon May 6 02:26:03 1996 +++ linux/arch/mips/kernel/time.c Thu Jun 26 12:33:37 1997 @@ -7,19 +7,26 @@ * found in some MIPS systems. */ #include +#include #include #include #include #include #include +#include -#include +#include +#include #include +#include #include #include -#define TIMER_IRQ 0 +extern volatile unsigned long lost_ticks; + +/* change this if you have some constant time drift */ +#define USECS_PER_JIFFY (1000020/HZ) /* This function must be called with interrupts disabled * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs @@ -58,22 +65,64 @@ static unsigned long do_slow_gettimeoffset(void) { int count; - unsigned long offset = 0; + + static int count_p = LATCH; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; /* 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; - } + + /* + * We do this guaranteed double memory access instead of a _p + * postfix in the previous port access. Wheee, hackady hack + */ + jiffies_t = jiffies; + + count |= inb_p(0x40) << 8; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there are two kinds of problems that must be avoided here: + * 1. the timer counter underflows + * 2. hardware problem with the timer, not giving us continuous time, + * the counter does small "jumps" upwards on some Pentium systems, + * (see c't 95/10 page 335 for Neptun bug.) + */ + + if( jiffies_t == jiffies_p ) { + if( count > count_p ) { + /* the nutcase */ + + outb_p(0x0A, 0x20); + + /* assumption about timer being IRQ1 */ + if( inb(0x20) & 0x01 ) { + /* + * We cannot detect lost timer interrupts ... + * well, thats why we call them lost, dont we? :) + * [hmm, on the Pentium and Alpha we can ... sort of] + */ + count -= LATCH; + } else { + printk("do_slow_gettimeoffset(): hardware timer problem?\n"); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + count = ((LATCH-1) - count) * TICK_SIZE; count = (count + LATCH/2) / LATCH; - return offset + count; + + return count; } static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; @@ -89,11 +138,20 @@ cli(); *tv = xtime; tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + if (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec++; } - restore_flags(flags); } void do_settimeofday(struct timeval *tv) @@ -114,8 +172,8 @@ xtime = *tv; time_state = TIME_BAD; - time_maxerror = 0x70000000; - time_esterror = 0x70000000; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; sti(); } @@ -166,7 +224,7 @@ /* 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 + * battery and quartz) 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 @@ -184,7 +242,7 @@ * 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) +static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { do_timer(regs); @@ -204,7 +262,7 @@ basically because we don't yet share IRQ's around. This message is rigged to be safe on the 386 - basically it's a hack, so don't look closely for now.. */ - smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); + /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -238,9 +296,12 @@ )*60 + sec; /* finally seconds */ } -void time_init(void) +static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL}; + +void (*board_time_init)(struct irqaction *irq); + +__initfunc(void time_init(void)) { - void (*irq_handler)(int, struct pt_regs *); unsigned int year, mon, day, hour, min, sec; int i; @@ -273,14 +334,16 @@ BCD_TO_BIN(mon); BCD_TO_BIN(year); } +#if 0 /* the IBM way */ if ((year += 1900) < 1970) year += 100; +#else + /* Acer PICA clock starts from 1980. True for all MIPS machines? */ + year += 1980; +#endif 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!"); + board_time_init(&irq0); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.1.43/linux/arch/mips/kernel/traps.c Tue May 13 22:41:02 1997 +++ linux/arch/mips/kernel/traps.c Thu Jun 26 12:33:37 1997 @@ -1,5 +1,5 @@ /* - * arch/mips/kernel/traps.c + * arch/mips/kernel/traps.c * * 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 @@ -13,26 +13,31 @@ * but possibly by killing it outright if necessary). * * FIXME: This is the place for a fpu emulator. + * + * Modified for R3000 by Paul M. Antoine, 1995, 1996 */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include +#include #include -#include #include -#include -#include #include -#include #include +#include +#include +#include + +#ifdef CONFIG_SGI +#include +#endif + +#undef CONF_DEBUG_EXCEPTIONS static inline void console_verbose(void) { @@ -49,9 +54,12 @@ 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); +extern asmlinkage void r4k_handle_mod(void); +extern asmlinkage void r2300_handle_mod(void); +extern asmlinkage void r4k_handle_tlbl(void); +extern asmlinkage void r2300_handle_tlbl(void); +extern asmlinkage void r4k_handle_tlbs(void); +extern asmlinkage void r2300_handle_tlbs(void); extern asmlinkage void handle_adel(void); extern asmlinkage void handle_ades(void); extern asmlinkage void handle_ibe(void); @@ -71,6 +79,10 @@ static char *cpu_names[] = CPU_NAMES; unsigned long page_colour_mask; +unsigned int watch_available = 0; + +void (*ibe_board_handler)(struct pt_regs *regs); +void (*dbe_board_handler)(struct pt_regs *regs); int kstack_depth_to_print = 24; @@ -80,48 +92,54 @@ */ #define MODULE_RANGE (8*1024*1024) -void die_if_kernel(char * str, struct pt_regs * regs, long err) +/* + * This routine abuses get_user()/put_user() to reference pointers + * with at least a bit of error checking ... + */ +void show_registers(char * str, struct pt_regs * regs, long err) { 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 = (u32 *)regs->reg29; + sp = (u32 *)regs->regs[29]; pc = (u32 *)regs->cp0_epc; - console_verbose(); - printk("%s: %08lx\n", str, err ); - show_regs(regs); /* * Dump the stack */ - if (STACK_MAGIC != *(u32 *)current->kernel_stack_page) - printk("Corrupted stack page\n"); printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ", - current->comm, current->pid, current->kernel_stack_page); + current->comm, current->pid, (unsigned long)current); for(i=0;i<5;i++) printk("%08x ", *sp++); stack = (int *) sp; + for(i=0; i < kstack_depth_to_print; i++) { + unsigned int stackdata; + if (((u32) stack & (PAGE_SIZE -1)) == 0) break; if (i && ((i % 8) == 0)) printk("\n "); - printk("%08lx ", get_user(stack++)); + if (get_user(stackdata, stack++) < 0) { + printk("(Bad stack address)"); + break; + } + printk("%08x ", stackdata); } printk("\nCall Trace: "); stack = (int *)sp; i = 1; module_start = VMALLOC_START; module_end = module_start + MODULE_RANGE; - while (((u32)stack & (PAGE_SIZE -1)) != 0) { - addr = get_user(stack++); + while (((unsigned long)stack & (PAGE_SIZE -1)) != 0) { + if (get_user(addr, stack++) < 0) { + printk("(Bad address)\n"); + break; + } /* * If the address is either in the text segment of the * kernel, or in the region which contains vmalloc'ed @@ -141,9 +159,7 @@ } printk("\nCode : "); - if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) || - KSEGX(pc) == KSEG0 || - KSEGX(pc) == KSEG1) && + if ((KSEGX(pc) == KSEG0 || KSEGX(pc) == KSEG1) && (((unsigned long) pc & 3) == 0)) { for(i=0;i<5;i++) @@ -152,230 +168,353 @@ } 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) +void die_if_kernel(const char * str, struct pt_regs * regs, long err) { - if(current->tss.mflags & MF_FIXADE) - { - fix_ade(regs, 0); + /* + * Just return if in user mode. + * XXX + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) + if (!((regs)->cp0_status & 0x4)) return; - } +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) + if (!(regs->cp0_status & 0x18)) + return; +#endif + console_verbose(); + printk("%s: %04lx\n", str, err & 0xffff); show_regs(regs); -while(1); - dump_tlb_nonwired(); - send_sig(SIGSEGV, current, 1); + do_exit(SIGSEGV); } -void do_ades(struct pt_regs *regs) +static void default_be_board_handler(struct pt_regs *regs) { - struct task_struct *p; - unsigned long pc = regs->cp0_epc; - int i; - - if(current->tss.mflags & MF_FIXADE) - { - fix_ade(regs, 1); - return; - } -while(1); - read_lock(&tasklist_lock); - for_each_task(p) { - if(p->pid >= 2) { - printk("Process %d\n", p->pid); - dump_list_process(p, pc); - } - } - read_unlock(&tasklist_lock); - show_regs(regs); - dump_tlb_nonwired(); - send_sig(SIGSEGV, current, 1); + /* + * Assume it would be too dangerous to continue ... + */ + force_sig(SIGBUS, current); } -/* - * 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) { -show_regs(regs); -while(1); - send_sig(SIGBUS, current, 1); + lock_kernel(); + ibe_board_handler(regs); + unlock_kernel(); } void do_dbe(struct pt_regs *regs) { -show_regs(regs); -while(1); - send_sig(SIGBUS, current, 1); + lock_kernel(); + dbe_board_handler(regs); + unlock_kernel(); } void do_ov(struct pt_regs *regs) { -show_regs(regs); -while(1); - send_sig(SIGFPE, current, 1); + lock_kernel(); +#ifdef CONF_DEBUG_EXCEPTIONS + show_regs(regs); +#endif + if (compute_return_epc(regs)) + goto out; + force_sig(SIGFPE, current); +out: + unlock_kernel(); } -void do_fpe(struct pt_regs *regs) +void do_fpe(struct pt_regs *regs, unsigned int fcr31) { -show_regs(regs); -while(1); - send_sig(SIGFPE, current, 1); + lock_kernel(); +#ifdef CONF_DEBUG_EXCEPTIONS + show_regs(regs); +#endif + printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n", + regs->cp0_epc, fcr31); + if (compute_return_epc(regs)) + goto out; + force_sig(SIGFPE, current); +out: + unlock_kernel(); +} + +static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) +{ + unsigned int *epc; + + epc = (unsigned int *) (unsigned long) regs->cp0_epc; + if (regs->cp0_cause & CAUSEF_BD) + epc += 4; + + if (verify_area(VERIFY_READ, epc, 4)) { + force_sig(SIGSEGV, current); + return 1; + } + *opcode = *epc; + + return 0; +} + +static inline void +do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode) +{ + /* + * (A short test says that IRIX 5.3 sends SIGTRAP for all break + * insns, even for break codes that indicate arithmetic failures. + * Wiered ...) + */ + force_sig(SIGTRAP, current); +#ifdef CONF_DEBUG_EXCEPTIONS + show_regs(regs); +#endif } void do_bp(struct pt_regs *regs) { -show_regs(regs); -while(1); - send_sig(SIGILL, current, 1); + unsigned int opcode, bcode; + + lock_kernel(); + /* + * There is the ancient bug in the MIPS assemblers that the break + * code starts left to bit 16 instead to bit 6 in the opcode. + * Gas is bug-compatible ... + */ +#ifdef CONF_DEBUG_EXCEPTIONS + printk("BREAKPOINT at %08lx\n", regs->cp0_epc); +#endif + if (get_insn_opcode(regs, &opcode)) + goto out; + bcode = ((opcode >> 16) & ((1 << 20) - 1)); + + do_bp_and_tr(regs, "bp", bcode); + + if (compute_return_epc(regs)) + goto out; +out: + unlock_kernel(); } void do_tr(struct pt_regs *regs) { -show_regs(regs); -while(1); - send_sig(SIGILL, current, 1); + unsigned int opcode, bcode; + + lock_kernel(); + if (get_insn_opcode(regs, &opcode)) + goto out; + bcode = ((opcode >> 6) & ((1 << 20) - 1)); + + do_bp_and_tr(regs, "tr", bcode); +out: + unlock_kernel(); } void do_ri(struct pt_regs *regs) { - struct task_struct *p; - int i; - - read_lock(&tasklist_lock); - for_each_task(p) { - if(p->pid >= 2) { - printk("Process %d\n", p->pid); - dump_list_process(p, 0x7ffff000); - } - } + lock_kernel(); +#ifdef CONF_DEBUG_EXCEPTIONS show_regs(regs); -while(1); - send_sig(SIGILL, current, 1); +#endif + printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", + current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + if (compute_return_epc(regs)) + goto out; + force_sig(SIGILL, current); +out: + unlock_kernel(); } void do_cpu(struct pt_regs *regs) { unsigned int cpid; + lock_kernel(); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; - switch(cpid) + if (cpid == 1) { - 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; + goto out; } + force_sig(SIGILL, current); +out: + unlock_kernel(); } void do_vcei(struct pt_regs *regs) { + lock_kernel(); /* - * Only possible on R4[04]00[SM]C. No handler because - * I don't have such a cpu. + * Only possible on R4[04]00[SM]C. No handler because I don't have + * such a cpu. Theory says this exception doesn't happen. */ - panic("Caught VCEI exception - can't handle yet\n"); + panic("Caught VCEI exception - should not happen"); + unlock_kernel(); } void do_vced(struct pt_regs *regs) { + lock_kernel(); /* - * Only possible on R4[04]00[SM]C. No handler because - * I don't have such a cpu. + * Only possible on R4[04]00[SM]C. No handler because I don't have + * such a cpu. Theory says this exception doesn't happen. */ - panic("Caught VCED exception - can't handle yet\n"); + panic("Caught VCE exception - should not happen"); + unlock_kernel(); } void do_watch(struct pt_regs *regs) { - panic("Caught WATCH exception - can't handle yet\n"); + lock_kernel(); + /* + * We use the watch exception where available to detect stack + * overflows. + */ + show_regs(regs); + panic("Caught WATCH exception - probably caused by stack overflow."); + unlock_kernel(); } void do_reserved(struct pt_regs *regs) { + lock_kernel(); /* * Game over - no way to handle this if it ever occurs. * Most probably caused by a new unknown cpu type or * after another deadly hard/software error. */ - panic("Caught reserved exception - can't handle.\n"); + panic("Caught reserved exception - should not happen."); + unlock_kernel(); } -void trap_init(void) +static inline void watch_init(unsigned long cputype) { - unsigned long i; - void watch_set(unsigned long, unsigned long); + switch(cputype) { + case CPU_R10000: + case CPU_R4000MC: + case CPU_R4400MC: + case CPU_R4000SC: + case CPU_R4400SC: + case CPU_R4000PC: + case CPU_R4400PC: + case CPU_R4200: + case CPU_R4300: + set_except_vector(23, handle_watch); + watch_available = 1; + break; + } +} - if(boot_info.machtype == MACH_MIPS_MAGNUM_4000) +typedef asmlinkage int (*syscall_t)(void *a0,...); +asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg); +extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs, + syscall_t fun, int narg); +extern asmlinkage int r2300_do_syscalls(struct pt_regs *regs, + syscall_t fun, int narg); + +asmlinkage void (*save_fp_context)(struct sigcontext *sc); +extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc); +extern asmlinkage void r2300_save_fp_context(struct sigcontext *sc); +extern asmlinkage void r6000_save_fp_context(struct sigcontext *sc); + +asmlinkage void (*restore_fp_context)(struct sigcontext *sc); +extern asmlinkage void r4k_restore_fp_context(struct sigcontext *sc); +extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc); +extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc); + +extern asmlinkage void r4xx0_resume(void *tsk); +extern asmlinkage void r2300_resume(void *tsk); + +__initfunc(void trap_init(void)) +{ + extern char except_vec0_r4000, except_vec0_r4600, except_vec0_r2300; + extern char except_vec1_generic, except_vec2_generic; + extern char except_vec3_generic, except_vec3_r4000; + unsigned long i; + + if(mips_machtype == MACH_MIPS_MAGNUM_4000 || + mips_machtype == MACH_DESKSTATION_RPC44 || + mips_machtype == MACH_SNI_RM200_PCI) EISA_bus = 1; + /* Copy the generic exception handler code to it's final destination. */ + memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + /* * Setup default vectors */ - for (i=0;i<=31;i++) + for(i = 0; i <= 31; i++) set_except_vector(i, handle_reserved); /* - * Handling the following exceptions depends mostly of the cpu type + * Only some CPUs have the watch exception. */ - switch(boot_info.cputype) { + watch_init(mips_cputype); + /* - * The R10000 is in most aspects similar to the R4400. It however - * should get some special optimizations. + * Handling the following exceptions depends mostly of the cpu type */ + switch(mips_cputype) { case CPU_R10000: + /* + * The R10000 is in most aspects similar to the R4400. It + * should get some special optimizations. + */ write_32bit_cp0_register(CP0_FRAMEMASK, 0); set_cp0_status(ST0_XX, ST0_XX); + /* + * Actually this mask stands for only 16k cache. This is + * correct since the R10000 has multiple ways in it's cache. + */ page_colour_mask = 0x3000; + /* + * The R10k might even work for Linux/MIPS - but we're paranoid + * and refuse to run until this is tested on real silicon + */ 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. If should ever be used - - * otherwise it's a bug in the Linux/MIPS kernel, anyway. + /* XXX The following won't work because we _cannot_ + * XXX perform any load/store before the VCE handler. */ set_except_vector(14, handle_vcei); set_except_vector(31, handle_vced); case CPU_R4000PC: case CPU_R4400PC: case CPU_R4200: - /* case CPU_R4300: */ + case CPU_R4300: + /* case CPU_R4640: */ + case CPU_R4600: + case CPU_R5000: + if(mips_cputype != CPU_R4600) + memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); + else + memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); + /* - * Use watch exception to trap on access to address zero + * The idea is that this special r4000 general exception + * vector will check for VCE exceptions before calling + * out of the exception array. XXX TODO */ - set_except_vector(23, handle_watch); - 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); + memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); + + do_syscalls = r4k_do_syscalls; + save_fp_context = r4k_save_fp_context; + restore_fp_context = r4k_restore_fp_context; + resume = r4xx0_resume; + set_except_vector(1, r4k_handle_mod); + set_except_vector(2, r4k_handle_tlbl); + set_except_vector(3, r4k_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 @@ -394,36 +533,89 @@ /* * 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? + * size of the data cache. */ i = read_32bit_cp0_register(CP0_CONFIG); i = (i >> 26) & 7; page_colour_mask = 1 << (12 + i); break; + case CPU_R6000: + case CPU_R6000A: + save_fp_context = r6000_save_fp_context; + restore_fp_context = r6000_restore_fp_context; +#if 0 + /* + * The R6000 is the only R-series CPU that features a machine + * check exception (similar to the R4000 cache error) and + * unaligned ldc1/sdc1 exception. The handlers have not been + * written yet. Well, anyway there is no R6000 machine on the + * current list of targets for Linux/MIPS. + */ + set_except_vector(14, handle_mc); + set_except_vector(15, handle_ndc); +#endif case CPU_R2000: case CPU_R3000: case CPU_R3000A: + /* + * Actually don't know about these, but let's guess - PMA + */ + memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); + do_syscalls = r2300_do_syscalls; + save_fp_context = r2300_save_fp_context; + restore_fp_context = r2300_restore_fp_context; + resume = r2300_resume; + set_except_vector(1, r2300_handle_mod); + set_except_vector(2, r2300_handle_tlbl); + set_except_vector(3, r2300_handle_tlbs); + set_except_vector(4, handle_adel); + set_except_vector(5, handle_ades); + /* + * The Data Bus Error/ Instruction Bus Errors are signaled + * by external hardware. Therefore these two expection have + * board specific handlers. + */ + set_except_vector(6, handle_ibe); + set_except_vector(7, handle_dbe); + ibe_board_handler = default_be_board_handler; + dbe_board_handler = default_be_board_handler; + + set_except_vector(8, handle_sys); + set_except_vector(9, handle_bp); + set_except_vector(10, handle_ri); + set_except_vector(11, handle_cpu); + 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? + * + * FIXME: is any of this necessary for the R3000, which + * doesn't have a config register? + * (No, the R2000, R3000 family has a physical indexed + * cache and doesn't need this braindamage.) + i = read_32bit_cp0_register(CP0_CONFIG); + i = (i >> 26) & 7; + page_colour_mask = 1 << (12 + i); + */ + break; case CPU_R3041: case CPU_R3051: case CPU_R3052: case CPU_R3081: case CPU_R3081E: - case CPU_R6000: - case CPU_R6000A: case CPU_R8000: printk("Detected unsupported CPU type %s.\n", - cpu_names[boot_info.cputype]); - panic("Can't handle CPU\n"); + cpu_names[mips_cputype]); + panic("Can't handle CPU"); break; case CPU_UNKNOWN: default: panic("Unknown CPU type"); } - - /* - * The interrupt handler mostly depends of the board type. - */ - set_except_vector(0, feature->handle_int); + flush_cache_all(); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/tyne-c.c linux/arch/mips/kernel/tyne-c.c --- v2.1.43/linux/arch/mips/kernel/tyne-c.c Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/kernel/tyne-c.c Wed Dec 31 16:00:00 1969 @@ -1,122 +0,0 @@ -/* - * 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 v2.1.43/linux/arch/mips/kernel/tyne.S linux/arch/mips/kernel/tyne.S --- v2.1.43/linux/arch/mips/kernel/tyne.S Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/kernel/tyne.S Wed Dec 31 16:00:00 1969 @@ -1,128 +0,0 @@ -/* - * 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 v2.1.43/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.1.43/linux/arch/mips/kernel/unaligned.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/unaligned.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,467 @@ +/* + * Handle unaligned accesses by emulation. + * + * 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) 1996 by Ralf Baechle + * + * This file contains exception handler for address error exception with the + * special capability to execute faulting instructions in software. The + * handler does not try to handle the case when the program counter points + * to an address not aligned to a word boundary. + * + * Putting data to unaligned addresses is a bad practice even on Intel where + * only the performance is affected. Much worse is that such code is non- + * portable. Due to several programs that die on MIPS due to alignment + * problems I decieded to implement this handler anyway though I originally + * didn't intend to do this at all for user code. + * + * For now I enable fixing of address errors by default to make life easier. + * I however intend to disable this somewhen in the future when the alignment + * problems with user programs have been fixed. For programmers this is the + * right way to go. + * + * Fixing address errors is a per process option. The option is inherited + * across fork(2) and execve(2) calls. If you really want to use the + * option in your user programs - I discourage the use of the software + * emulation strongly - use the following code in your userland stuff: + * + * #include + * + * ... + * sysmips(MIPS_FIXADE, x); + * ... + * + * The parameter x is 0 for disabeling software emulation. Set bit 0 for + * enabeling software emulation and bit 1 for enabeling printing debug + * messages into syslog to aid finding address errors in programs. + * + * The logging feature is an addition over RISC/os and IRIX where only the + * values 0 and 1 are acceptable values for x. I'll probably remove this + * hack later on. + * + * Below a little program to play around with this feature. + * + * #include + * #include + * + * struct foo { + * unsigned char bar[8]; + * }; + * + * main(int argc, char *argv[]) + * { + * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7}; + * unsigned int *p = (unsigned int *) (x.bar + 3); + * int i; + * + * if (argc > 1) + * sysmips(MIPS_FIXADE, atoi(argv[1])); + * + * printf("*p = %08lx\n", *p); + * + * *p = 0xdeadface; + * + * for(i = 0; i <= 7; i++) + * printf("%02x ", x.bar[i]); + * printf("\n"); + * } + * + * Until I've written the code to handle branch delay slots it may happen + * that the kernel receives an ades/adel instruction from an insn in a + * branch delay slot but is unable to handle this case. The kernel knows + * this fact and therefore will kill the process. For most code you can + * fix this temporarily by compiling with flags -fno-delayed-branch -Wa,-O0. + * + * Coprozessor loads are not supported; I think this case is unimportant + * in the practice. + * + * TODO: Handle ndc (attempted store to doubleword in uncached memory) + * exception for the R6000. + * A store crossing a page boundary might be executed only partially. + * Undo the partial store in this case. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#undef CONF_NO_UNALIGNED_KERNEL_ACCESS +#undef CONF_LOG_UNALIGNED_ACCESSES + +#define STR(x) __STR(x) +#define __STR(x) #x + +typedef unsigned long register_t; + +/* + * User code may only access USEG; kernel code may access the + * entire address space. + */ +#define check_axs(p,a,s) \ + if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ + goto sigbus; + +static inline void +emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long pc) +{ + union mips_instruction insn; + register_t value; + + regs->regs[0] = 0; + /* + * This load never faults. + */ + __get_user(insn.word, (unsigned int *)pc); + + switch (insn.i_format.opcode) { + /* + * These are instructions that a compiler doesn't generate. We + * can assume therefore that the code is MIPS-aware and + * really buggy. Emulating these instructions would break the + * semantics anyway. + */ + case ll_op: + case lld_op: + case sc_op: + case scd_op: + + /* + * For these instructions the only way to create an address + * error is an attempted access to kernel/supervisor address + * space. + */ + case ldl_op: + case ldr_op: + case lwl_op: + case lwr_op: + case sdl_op: + case sdr_op: + case swl_op: + case swr_op: + case lb_op: + case lbu_op: + case sb_op: + goto sigbus; + + /* + * The remaining opcodes are the ones that are really of interrest. + */ + case lh_op: + check_axs(pc, addr, 2); + __asm__( + ".set\tnoat\n" +#ifdef __BIG_ENDIAN + "1:\tlb\t%0,0(%1)\n" + "2:\tlbu\t$1,1(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tlb\t%0,1(%1)\n" + "2:\tlbu\t$1,0(%1)\n\t" +#endif + "sll\t%0,0x8\n\t" + "or\t%0,$1\n\t" + ".set\tat\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + :"=&r" (value) + :"r" (addr), "i" (&&fault) + :"$1"); + regs->regs[insn.i_format.rt] = value; + return; + + case lw_op: + check_axs(pc, addr, 4); + __asm__( +#ifdef __BIG_ENDIAN + "1:\tlwl\t%0,(%1)\n" + "2:\tlwr\t%0,3(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tlwl\t%0,3(%1)\n" + "2:\tlwr\t%0,(%1)\n\t" +#endif + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + :"=&r" (value) + :"r" (addr), "i" (&&fault)); + regs->regs[insn.i_format.rt] = value; + return; + + case lhu_op: + check_axs(pc, addr, 2); + __asm__( + ".set\tnoat\n" +#ifdef __BIG_ENDIAN + "1:\tlbu\t%0,0(%1)\n" + "2:\tlbu\t$1,1(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tlbu\t%0,1(%1)\n" + "2:\tlbu\t$1,0(%1)\n\t" +#endif + "sll\t%0,0x8\n\t" + "or\t%0,$1\n\t" + ".set\tat\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + :"=&r" (value) + :"r" (addr), "i" (&&fault) + :"$1"); + regs->regs[insn.i_format.rt] = value; + return; + + case lwu_op: + check_axs(pc, addr, 4); + __asm__( +#ifdef __BIG_ENDIAN + "1:\tlwl\t%0,(%1)\n" + "2:\tlwr\t%0,3(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tlwl\t%0,3(%1)\n" + "2:\tlwr\t%0,(%1)\n\t" +#endif + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + :"=&r" (value) + :"r" (addr), "i" (&&fault)); + value &= 0xffffffff; + regs->regs[insn.i_format.rt] = value; + return; + + case ld_op: + check_axs(pc, addr, 8); + __asm__( + ".set\tmips3\n" +#ifdef __BIG_ENDIAN + "1:\tldl\t%0,(%1)\n" + "2:\tldr\t%0,7(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tldl\t%0,7(%1)\n" + "2:\tldr\t%0,(%1)\n\t" +#endif + ".set\tmips0\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + :"=&r" (value) + :"r" (addr), "i" (&&fault)); + regs->regs[insn.i_format.rt] = value; + return; + + case sh_op: + check_axs(pc, addr, 2); + value = regs->regs[insn.i_format.rt]; + __asm__( +#ifdef __BIG_ENDIAN + ".set\tnoat\n" + "1:\tsb\t%0,1(%1)\n\t" + "srl\t$1,%0,0x8\n" + "2:\tsb\t$1,0(%1)\n\t" + ".set\tat\n\t" +#endif +#ifdef __LITTLE_ENDIAN + ".set\tnoat\n" + "1:\tsb\t%0,0(%1)\n\t" + "srl\t$1,%0,0x8\n" + "2:\tsb\t$1,1(%1)\n\t" + ".set\tat\n\t" +#endif + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + : /* no outputs */ + :"r" (value), "r" (addr), "i" (&&fault) + :"$1"); + return; + + case sw_op: + check_axs(pc, addr, 4); + value = regs->regs[insn.i_format.rt]; + __asm__( +#ifdef __BIG_ENDIAN + "1:\tswl\t%0,(%1)\n" + "2:\tswr\t%0,3(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tswl\t%0,3(%1)\n" + "2:\tswr\t%0,(%1)\n\t" +#endif + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + : /* no outputs */ + :"r" (value), "r" (addr), "i" (&&fault)); + return; + + case sd_op: + check_axs(pc, addr, 8); + value = regs->regs[insn.i_format.rt]; + __asm__( + ".set\tmips3\n" +#ifdef __BIG_ENDIAN + "1:\tsdl\t%0,(%1)\n" + "2:\tsdr\t%0,7(%1)\n\t" +#endif +#ifdef __LITTLE_ENDIAN + "1:\tsdl\t%0,7(%1)\n" + "2:\tsdr\t%0,(%1)\n\t" +#endif + ".set\tmips0\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,%2\n\t" + STR(PTR)"\t2b,%2\n\t" + ".previous" + : /* no outputs */ + :"r" (value), "r" (addr), "i" (&&fault)); + return; + + case lwc1_op: + case ldc1_op: + case swc1_op: + case sdc1_op: + /* + * I herewith declare: this does not happen. So send SIGBUS. + */ + goto sigbus; + + case lwc2_op: + case ldc2_op: + case swc2_op: + case sdc2_op: + /* + * These are the coprozessor 2 load/stores. The current + * implementations don't use cp2 and cp2 should always be + * disabled in c0_status. So send SIGILL. + * (No longer true: The Sony Praystation uses cp2 for + * 3D matrix operations. Dunno if that thingy has a MMU ...) + */ + default: + /* + * Pheeee... We encountered an yet unknown instruction ... + */ + force_sig(SIGILL, current); + } + return; + +fault: + send_sig(SIGSEGV, current, 1); + return; +sigbus: + send_sig(SIGBUS, current, 1); + return; +} + +unsigned long unaligned_instructions; + +static inline void +fix_ade(struct pt_regs *regs, unsigned long pc) +{ + /* + * Did we catch a fault trying to load an instruction? + */ + if (regs->cp0_badvaddr == pc) { + /* + * Phee... Either the code is severly messed up or the + * process tried to activate some MIPS16 code. + */ + force_sig(SIGBUS, current); + } + + /* + * Ok, this wasn't a failed instruction load. The CPU was capable of + * reading the instruction and faulted after this. So we don't need + * to verify_area the address of the instrucion. We still don't + * know whether the address used was legal and therefore need to do + * verify_area(). The CPU already did the checking for legal + * instructions for us, so we don't need to do this. + */ + emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); + unaligned_instructions++; +} + +#define kernel_address(x) ((long)(x) < 0) + +asmlinkage void +do_ade(struct pt_regs *regs) +{ + register_t pc = regs->cp0_epc; + register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr; + char *adels; + + lock_kernel(); + adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >> + CAUSEB_EXCCODE) == 4) ? "adel" : "ades"; + +#ifdef CONF_NO_UNALIGNED_KERNEL_ACCESS + /* + * In an ideal world there are no unaligned accesses by the kernel. + * So be a bit noisy ... + */ + if (kernel_address(badvaddr) && !user_mode(regs)) { + show_regs(regs); +#ifdef __mips64 + panic("Caught %s exception in kernel mode accessing %016Lx.", + adels, badvaddr); +#else + panic("Caught %s exception in kernel mode accessing %08lx.", + adels, badvaddr); +#endif + } +#endif /* CONF_NO_UNALIGNED_KERNEL_ACCESS */ + +#ifdef CONF_LOG_UNALIGNED_ACCESSES + if (current->tss.mflags & MF_LOGADE) { + register_t logpc = pc; + if (regs->cp0_cause & CAUSEF_BD) + logpc += 4; +#ifdef __mips64 + printk(KERN_DEBUG + "Caught %s in '%s' at 0x%016Lx accessing 0x%016Lx.\n", + adels, current->comm, logpc, regs->cp0_badvaddr); +#else + printk(KERN_DEBUG + "Caught %s in '%s' at 0x%08lx accessing 0x%08lx.\n", + adels, current->comm, logpc, regs->cp0_badvaddr); +#endif + } +#endif /* CONF_LOG_UNALIGNED_ACCESSES */ + + if (compute_return_epc(regs)) + goto out; + if(current->tss.mflags & MF_FIXADE) { + pc += ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); + fix_ade(regs, pc); + goto out; + } + +#ifdef CONF_DEBUG_EXCEPTIONS + show_regs(regs); +#endif + + force_sig(SIGBUS, current); + +out: + unlock_kernel(); + return; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/vm86.c linux/arch/mips/kernel/vm86.c --- v2.1.43/linux/arch/mips/kernel/vm86.c Fri Jan 13 08:21:20 1995 +++ linux/arch/mips/kernel/vm86.c Thu Jun 26 12:33:37 1997 @@ -6,9 +6,8 @@ */ #include #include -#include -asmlinkage int sys_vm86(struct vm86_struct * v86) +asmlinkage int sys_vm86(void *v86) { return -ENOSYS; } diff -u --recursive --new-file v2.1.43/linux/arch/mips/ld.script linux/arch/mips/ld.script --- v2.1.43/linux/arch/mips/ld.script Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/ld.script Wed Dec 31 16:00:00 1969 @@ -1,106 +0,0 @@ -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 v2.1.43/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big --- v2.1.43/linux/arch/mips/ld.script.big Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ld.script.big Thu Jun 26 12:33:37 1997 @@ -0,0 +1,106 @@ +OUTPUT_FORMAT("elf32-bigmips") +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 v2.1.43/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little --- v2.1.43/linux/arch/mips/ld.script.little Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ld.script.little Thu Jun 26 12:33:37 1997 @@ -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 v2.1.43/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.1.43/linux/arch/mips/lib/Makefile Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/lib/Makefile Thu Jun 26 12:33:37 1997 @@ -1,9 +1,6 @@ # # 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 @@ -11,6 +8,13 @@ $(CC) $(CFLAGS) -c $< -o $*.o L_TARGET = lib.a -L_OBJS = beep.o checksum.o csum.o dump_tlb.o tinycon.o watch.o +L_OBJS = checksum.o copy_user.o csum.o dump_tlb.o io.o \ + memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o + +ifdef CONFIG_DECSTATION +L_OBJS += pmaxcon.o pmaxio.o +else +L_OBJS += tinycon.o +endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c --- v2.1.43/linux/arch/mips/lib/checksum.c Thu Apr 11 23:49:30 1996 +++ linux/arch/mips/lib/checksum.c Thu Jun 26 12:33:37 1997 @@ -16,126 +16,85 @@ */ #include #include +#include + +static inline unsigned short from32to16(unsigned long x) +{ + /* 32 bits --> 16 bits + carry */ + x = (x & 0xffff) + (x >> 16); + /* 16 bits + carry --> 16 bits including carry */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static inline unsigned long do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} /* * 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 desirable 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"); + unsigned long result = do_csum(buff, len); - return sum; + /* add in old sum, and carry.. */ + result += sum; + if(sum > result) + result += 1; + return result; } /* - * copy from fs while checksumming, otherwise like csum_partial + * copy while checksumming, otherwise like csum_partial */ unsigned int csum_partial_copy(const char *src, char *dst, - int len, int sum) + int len, unsigned int sum) { /* * It's 2:30 am and I don't feel like doing it real ... @@ -145,4 +104,24 @@ memcpy(dst, src, len); return sum; +} + +/* + * Copy from userspace and compute checksum. If we catch an exception + * then zero the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user (const char *src, char *dst, + int len, unsigned int sum, + int *err_ptr) +{ + int *dst_err_ptr=NULL; + int missing; + + missing = copy_from_user(dst, src, len); + if (missing) { + memset(dst + len - missing, 0, missing); + *err_ptr = -EFAULT; + } + + return csum_partial(dst, len, sum); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/copy_user.S linux/arch/mips/lib/copy_user.S --- v2.1.43/linux/arch/mips/lib/copy_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/copy_user.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,207 @@ +/* + * arch/mips/mips1/memcpy.S + * + * 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) 1996 by Ralf Baechle + * + * Less stupid memcpy/user_copy implementation for 32 bit MIPS CPUs. + */ +#include +#include +#include + +#define BLOCK_SIZE 16 + +#define EX(addr,handler) \ + .section __ex_table,"a"; \ + PTR addr, handler; \ + .previous +#define UEX(addr,handler) \ + EX(addr,handler); \ + EX(addr+4,handler) + + .set noreorder + .set noat + +/* ---------------------------------------------------------------------- */ + +/* + * Bad. We can't fix the alignment for both address parts. + * Align the source address and copy slowly ... + */ +not_even_the_same_alignment: + LONG_SUBU v1,zero,a1 + andi v1,a1,3 + sltu t0,v0,v1 + MOVN(v1,v0,t0) + beqz v1,align4 # -> finished + LONG_ADDU v1,a0 # delay slot +1: lb $1,(a1) + EX(1b, fault) + LONG_ADDIU a1,1 +2: sb $1,(a0) + EX(2b, fault) + LONG_ADDIU a0,1 + bne a0,v1,1b + LONG_SUBU v0,1 # delay slot + +/* + * Ok. We've fixed the alignment of the copy src for this case. + * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned + * stores. + * XXX Align the destination address. This is better if the __copy_user + * encounters an access fault because we never have to deal with an + * only partially modified destination word. + */ + ori v1,v0,BLOCK_SIZE-1 + xori v1,BLOCK_SIZE-1 + beqz v1,copy_left_over + nop # delay slot + LONG_SUBU v0,v1 + LONG_ADDU v1,a0 + +1: lw t0,(a1) # Can cause tlb fault + EX(1b, fault) +2: lw t1,4(a1) # Can cause tlb fault + EX(2b, fault) +2: lw t2,8(a1) # Can cause tlb fault + EX(2b, fault) +2: lw t3,12(a1) # Can cause tlb fault + EX(2b, fault) +2: usw t0,(a0) # Can cause tlb faults + UEX(2b, fault) +2: usw t1,4(a0) # Can cause tlb faults + UEX(2b, fault_plus_4) +2: usw t2,8(a0) # Can cause tlb faults + UEX(2b, fault_plus_8) +2: usw t3,12(a0) # Can cause tlb faults + UEX(2b, fault_plus_12) + LONG_ADDIU a0,BLOCK_SIZE + bne a0,v1,1b + LONG_ADDIU a1,BLOCK_SIZE # delay slot +9: + b copy_left_over # < BLOCK_SIZE bytes left + nop # delay slot + +/* ---------------------------------------------------------------------- */ + +not_w_aligned: +/* + * Ok, src or destination are not 8-byte aligned. + * Try to fix that. Do at least both addresses have the same alignment? + */ + xor t0,a0,a1 + andi t0,3 + bnez t0,not_even_the_same_alignment + nop # delay slot + +/* + * Ok, we can fix the alignment for both operands and go back to the + * fast path. We have to copy at least one byte, on average 3 bytes + * bytewise. + */ + LONG_SUBU v1,zero,a0 + andi v1,3 + sltu t0,v0,v1 + MOVN(v1,v0,t0) + beqz v1,3f # -> finished + LONG_ADDU v1,a0 # delay slot +1: lb $1,(a1) + EX(1b, fault) + LONG_ADDIU a1,1 +2: sb $1,(a0) + EX(2b, fault) + LONG_ADDIU a0,1 + bne a0,v1,1b + LONG_SUBU v0,1 # delay slot + b align4 + nop # delay slot +3: + +/* ---------------------------------------------------------------------- */ + +LEAF(__copy_user) + or t1,a0,a1 + andi t1,3 + bnez t1,not_w_aligned + move v0,a2 # delay slot + +align4: + ori v1,v0,BLOCK_SIZE-1 + xori v1,BLOCK_SIZE-1 + beqz v1,copy_left_over + nop # delay slot + LONG_SUBU v0,v1 + LONG_ADDU v1,a0 + +1: lw t0,(a1) # Can cause tlb fault + EX(1b, fault) +2: lw t1,4(a1) # Can cause tlb fault + EX(2b, fault) +2: lw t2,8(a1) # Can cause tlb fault + EX(2b, fault) +2: lw t3,12(a1) # Can cause tlb fault + EX(2b, fault) +2: sw t0,(a0) # Can cause tlb fault + EX(2b, fault) +2: sw t1,4(a0) # Can cause tlb fault + EX(2b, fault_plus_4) +2: sw t2,8(a0) # Can cause tlb fault + EX(2b, fault_plus_8) +2: sw t3,12(a0) # Can cause tlb fault + EX(2b, fault_plus_12) + LONG_ADDIU a0,BLOCK_SIZE + bne a0,v1,1b + LONG_ADDIU a1,BLOCK_SIZE # delay slot +9: + +/* + * XXX Tune me ... + */ +copy_left_over: + beqz v0,3f + nop # delay slot +1: lb $1,(a1) + EX(1b, fault) + LONG_ADDIU a1,1 +2: sb $1,(a0) + EX(2b, fault) + LONG_SUBU v0,1 + bnez v0,1b + LONG_ADDIU a0,1 +3: jr ra + nop # delay slot + + END(__copy_user) + .set at + .set reorder + +/* ---------------------------------------------------------------------- */ + +/* + * Access fault. The number of not copied bytes is in v0. We have to + * correct the number of the not copied bytes in v0 in case of a access + * fault in an unrolled loop, then return. + */ + +fault: jr ra +fault_plus_4: LONG_ADDIU v0,4 + jr ra +fault_plus_8: LONG_ADDIU v0,8 + jr ra +fault_plus_12: LONG_ADDIU v0,12 + jr ra + +/* ---------------------------------------------------------------------- */ + +/* + * For now we use __copy_user for __memcpy, too. This is effizient (one + * instruction penatly) and smaller but adds unwanted error checking we don't + * need. This hopefully doesn't cover any bugs. The memcpy() wrapper in + * takes care of the return value in a way GCC can optimize. + */ + .globl __memcpy +__memcpy = __copy_user diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/csum.S linux/arch/mips/lib/csum.S --- v2.1.43/linux/arch/mips/lib/csum.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/csum.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,25 @@ +#include +#include +#include + +/* + * Compute kernel code checksum to check kernel code against corruption + * (Ancient debugging trash ...) + */ + LEAF(csum) + LONG_L t0,cacheflush + move t8,ra + jalr t0 + li t0,KSEG1 + la t1,final + li t2,KSEG1 + or t0,t2 + or t1,t2 + move v0,zero +1: lw t2,(t0) + addiu t0,4 + bne t0,t1,1b + xor v0,t2 + jr t8 + nop + END(csum) diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c --- v2.1.43/linux/arch/mips/lib/dump_tlb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/dump_tlb.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,148 @@ +/* + * Dump R4x00 TLB for debugging purposes. + * + * Copyright (C) 1994, 1995 by Waldorf Electronics, + * written by Ralf Baechle. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void +dump_tlb(int first, int last) +{ + int i; + int wired; + unsigned int pagemask; + unsigned long long entryhi, entrylo0, entrylo1; + + wired = read_32bit_cp0_register(CP0_WIRED); + printk("Wired: %d", wired); + + for(i=first;i> 32), + (unsigned int) entryhi); + printk(" %08x %08x", (unsigned int)(entrylo0 >> 32), + (unsigned int) entrylo0); + printk(" %08x %08x", (unsigned int)(entrylo1 >> 32), + (unsigned int) entrylo1); + } + } + printk("\n"); +} + +void +dump_tlb_all(void) +{ + dump_tlb(0, mips_tlb_entries - 1); +} + +void +dump_tlb_wired(void) +{ + dump_tlb(0, read_32bit_cp0_register(CP0_WIRED)); +} + +void +dump_tlb_nonwired(void) +{ + dump_tlb(read_32bit_cp0_register(CP0_WIRED), mips_tlb_entries - 1); +} + +void +dump_list_process(struct task_struct *t, void *address) +{ + pgd_t *page_dir, *pgd; + pmd_t *pmd; + pte_t *pte, page; + unsigned int addr; + + addr = (unsigned int) address; + + printk("Addr == %08x\n", addr); + printk("tasks->tss.pg_dir == %08x\n", (unsigned int) t->tss.pg_dir); + printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); + + page_dir = pgd_offset(t->mm, 0); + printk("page_dir == %08x\n", (unsigned int) page_dir); + + pgd = pgd_offset(t->mm, addr); + printk("pgd == %08x, ", (unsigned int) pgd); + + pmd = pmd_offset(pgd, addr); + printk("pmd == %08x, ", (unsigned int) pmd); + + pte = pte_offset(pmd, addr); + printk("pte == %08x, ", (unsigned int) pte); + + page = *pte; + printk("page == %08x\n", (unsigned int) pte_val(page)); +} + +void +dump_list_current(void *address) +{ + dump_list_process(current, address); +} + +unsigned int +vtop(void *address) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned int addr, paddr; + + addr = (unsigned long) address; + pgd = pgd_offset(current->mm, addr); + pmd = pmd_offset(pgd, addr); + pte = pte_offset(pmd, addr); + paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK; + paddr |= (addr & ~PAGE_MASK); + + return paddr; +} + +void +dump16(unsigned long *p) +{ + int i; + + for(i=0;i<8;i++) + { + printk("*%08lx == %08lx, ", + (unsigned long)p, (unsigned long)*p++); + printk("*%08lx == %08lx\n", + (unsigned long)p, (unsigned long)*p++); + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/io.c linux/arch/mips/lib/io.c --- v2.1.43/linux/arch/mips/lib/io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/io.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,24 @@ +/* + * include/asm-mips/string.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, 1996 by Ralf Baechle + * + * For now io.c contains only the definition of isa_slot_offset. The + * real io.S doesn't assemble due to a GAS bug. + */ + +/* + * port_base is the begin of the address space to which x86 style + * I/O ports are mapped. + */ +unsigned long port_base; + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped + * for the processor. + */ +unsigned long isa_slot_offset; diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.1.43/linux/arch/mips/lib/memcpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/memcpy.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,221 @@ +/* memcpy.S: Mips optimized memcpy based upon SparcLinux code. + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1996 David S. Miller + * Copyright(C) 1996 Eddie C. Dost + * + * derived from: + * e-mail between David and Eddie. + */ + +#include +#include + +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5) \ + lw t0, (offset + 0x18)(src); \ + lw t1, (offset + 0x1c)(src); \ + sw t0, (offset + 0x18)(dst); \ + lw t2, (offset + 0x10)(src); \ + sw t1, (offset + 0x1c)(dst); \ + lw t3, (offset + 0x14)(src); \ + sw t2, (offset + 0x10)(dst); \ + lw t4, (offset + 0x08)(src); \ + sw t3, (offset + 0x14)(dst); \ + lw t5, (offset + 0x0c)(src); \ + sw t4, (offset + 0x08)(dst); \ + lw t0, (offset + 0x00)(src); \ + sw t5, (offset + 0x0c)(dst); \ + lw t1, (offset + 0x04)(src); \ + sw t0, (offset + 0x00)(dst); \ + sw t1, (offset + 0x04)(dst); \ + + /* Alignment cases are: + * 1) (src&0x3)=0x0 (dst&0x3)=0x0 can optimize + * 2) (src&0x3)=0x1 (dst&0x3)=0x1 can optimize + * 3) (src&0x3)=0x2 (dst&0x3)=0x2 can optimize + * 4) (src&0x3)=0x3 (dst&0x3)=0x3 can optimize + * 5) anything else cannot optimize + */ + + /* I hate MIPS register names... AIEEE, it's a SPARC! */ +#define o0 a0 +#define o1 a1 +#define o2 a2 +#define o3 a3 +#define o4 t0 +#define o5 t1 +#define o6 sp +#define o7 ra +#define g0 zero +#define g1 t2 +#define g2 t3 +#define g3 t4 +#define g4 t5 +#define g5 t6 +#define g6 t7 +#define g7 t8 + + .text + .set noreorder + .set noat + + .globl bcopy + .globl amemmove + .globl memmove + .globl memcpy + .align 2 +bcopy: + move o3, o0 + move o0, o1 + move o1, o3 + +amemmove: +memmove: +memcpy: /* o0=dst o1=src o2=len */ + xor o4, o0, o1 + andi o4, o4, 0x3 + move g6, o0 + beq o4, g0, can_align + sltiu g7, o2, 0x8 + + b cannot_optimize + move g1, o2 + +can_align: + bne g7, g0, cannot_optimize + move g1, o2 + + beq o2, g0, out + andi g7, o1, 0x1 + +hword_align: + beq g7, g0, word_align + andi g7, o1, 0x2 + + lbu o4, 0x00(o1) + subu o2, o2, 0x1 + sb o4, 0x00(o0) + addu o1, o1, 0x1 + addu o0, o0, 0x1 + andi g7, o1, 0x2 + +word_align: + beq g7, g0, dword_align + sltiu g7, o2, 56 + + lhu o4, 0x00(o1) + subu o2, o2, 0x2 + sh o4, 0x00(o0) + sltiu g7, o2, 56 + addu o0, o0, 0x2 + addu o1, o1, 0x2 + +dword_align: + bne g7, g0, do_end_words + move g7, o2 + + andi g7, o1, 0x4 + beq g7, zero, qword_align + andi g7, o1, 0x8 + + lw o4, 0x00(o1) + subu o2, o2, 0x4 + sw o4, 0x00(o0) + addu o1, o1, 0x4 + addu o0, o0, 0x4 + andi g7, o1, 0x8 + +qword_align: + beq g7, g0, oword_align + andi g7, o1, 0x10 + + lw o4, 0x00(o1) + lw o5, 0x04(o1) + subu o2, o2, 0x8 + sw o4, 0x00(o0) + addu o1, o1, 0x8 + sw o5, 0x04(o0) + andi g7, o1, 0x10 + addu o0, o0, 0x8 + +oword_align: + beq g7, g0, begin_movement + srl g7, o2, 0x7 + + lw g2, 0x08(o1) + lw g3, 0x0c(o1) + lw o4, 0x00(o1) + lw o5, 0x04(o1) + sw g2, 0x08(o0) + subu o2, o2, 0x10 + sw g3, 0x0c(o0) + addu o1, o1, 0x10 + sw o4, 0x00(o0) + srl g7, o2, 0x7 + addu o0, o0, 0x10 + sw o5, -0x0c(o0) + +begin_movement: + beq g7, g0, 0f + andi g1, o2, 0x40 + +move_128bytes: + MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x40, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x60, o4, o5, g2, g3, g4, g5) + subu g7, g7, 0x01 + addu o1, o1, 0x80 + bne g7, g0, move_128bytes + addu o0, o0, 0x80 + +0: + beq g1, g0, 1f + andi g1, o2, 0x20 + +move_64bytes: + MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5) + addu o1, o1, 0x40 + addu o0, o0, 0x40 + +1: + beq g1, g0, do_end_words + andi g7, o2, 0x1c + +move_32bytes: + MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) + andi g7, o2, 0x1c + addu o1, o1, 0x20 + addu o0, o0, 0x20 + +do_end_words: + beq g7, g0, maybe_end_cruft + srl g7, g7, 0x2 + +end_words: + lw o4, 0x00(o1) + subu g7, g7, 0x1 + sw o4, 0x00(o0) + addu o1, o1, 0x4 + bne g7, g0, end_words + addu o0, o0, 0x4 + +maybe_end_cruft: + andi g1, o2, 0x3 + +cannot_optimize: + beq g1, g0, out + move o2, g1 + +end_bytes: + lbu o4, 0x00(o1) + subu o2, o2, 0x1 + sb o4, 0x00(o0) + addu o1, o1, 0x1 + bne o2, g0, end_bytes + addu o0, o0, 0x1 + +out: + jr o7 + move v0, g6 diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/memset.c linux/arch/mips/lib/memset.c --- v2.1.43/linux/arch/mips/lib/memset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/memset.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,71 @@ +/* linux/arch/mips/lib/memset.c + * + * This is from GNU libc. + */ + +#include + +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +typedef unsigned char byte; + +void *memset(void *dstpp, char c, size_t len) +{ + long int dstp = (long int) dstpp; + + if (len >= 8) { + size_t xlen; + op_t cccc; + + cccc = (unsigned char) c; + cccc |= cccc << 8; + cccc |= cccc << 16; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + while (dstp % OPSIZ != 0) { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + /* Write 8 `op_t' per iteration until less + * than 8 `op_t' remain. + */ + xlen = len / (OPSIZ * 8); + while (xlen > 0) { + ((op_t *) dstp)[0] = cccc; + ((op_t *) dstp)[1] = cccc; + ((op_t *) dstp)[2] = cccc; + ((op_t *) dstp)[3] = cccc; + ((op_t *) dstp)[4] = cccc; + ((op_t *) dstp)[5] = cccc; + ((op_t *) dstp)[6] = cccc; + ((op_t *) dstp)[7] = cccc; + dstp += 8 * OPSIZ; + xlen -= 1; + } + len %= OPSIZ * 8; + + /* Write 1 `op_t' per iteration until less than + * OPSIZ bytes remain. + */ + xlen = len / OPSIZ; + while (xlen > 0) { + ((op_t *) dstp)[0] = cccc; + dstp += OPSIZ; + xlen -= 1; + } + len %= OPSIZ; + } + + /* Write the last few bytes. */ + while (len > 0) { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + return dstpp; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/pmaxcon.c linux/arch/mips/lib/pmaxcon.c --- v2.1.43/linux/arch/mips/lib/pmaxcon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/pmaxcon.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,150 @@ +/* ---------------------------------------------------------------------- + * console.c + * + * Copyright (C) 1994 by Waldorf Electronic, + * written by Ralf Baechle and Andreas Busse + * Copyright (C) 1995 Paul M. Antoine (PMAX) + * + * 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. + * ---------------------------------------------------------------------- */ +/* + * FIXME: This file is hacked to be hardwired for the Personal DECStation + * Only thought of as a debugging console output + */ + +#include +#include + +static unsigned int size_x; +static unsigned int size_y; +static unsigned short cursor_x; +static unsigned short cursor_y; +static volatile unsigned short *vram_addr; +static int console_needs_init = 1; + +extern struct bootinfo boot_info; +extern struct screen_info screen_info; + +/* + * Here is the base address of the prom calls + */ +unsigned long pmax_rex_base = 0; + +/* ---------------------------------------------------------------------- + * init_console() + * ---------------------------------------------------------------------- */ + +void init_console(void) +{ + size_x = 80; + size_y = 50; + cursor_x = 0; + cursor_y = 0; + + vram_addr = (unsigned short *)0xe10b8000; + + console_needs_init = 0; +} + +void +set_size_x(unsigned int x) +{ + size_x = x; +} + +void +set_size_y(unsigned int y) +{ + size_y = y; +} + +void +set_vram(unsigned short *vram) +{ + vram_addr = vram; +} + +/* + * FIXME: Temporary hack - changed its name to avoid conflict in + * drivers/char/vga.c that shouldn't be there PMA + */ +void +set_pmax_cursor(unsigned int x, unsigned int y) +{ + cursor_x = x; + cursor_y = y; +} + +void +print_char(unsigned int x, unsigned int y, unsigned char c) +{ + volatile unsigned short *caddr; + +/* caddr = vram_addr + (y * size_x) + x; + *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c; +*/ + pmax_putch(c); +} + +static void +scroll(void) +{ + volatile unsigned short *caddr; + register int i; +/* + caddr = vram_addr; + for(i=0; i +#include + + .text + .set reorder +/* + * pmax_printf - call the PROM printf() function + */ + .globl pmax_printf +pmax_printf: + lw v0,pmax_rex_base + lw v0,REX_PRINTF(v0) + j v0 + +/* + * pmax_getchar - call the PROM getchar() function + */ + .globl pmax_getch +pmax_getch: + lw v0,pmax_rex_base + lw v0,REX_GETCHAR(v0) + j v0 + +/* + * pmax_putchar - call the PROM putchar() function + */ + .globl pmax_putch +pmax_putch: + lw v0,pmax_rex_base + lw v0,REX_PUTCHAR(v0) + j v0 + +/* + * pmax_halt - call the PROM halt() function + */ + .globl pmax_halt +pmax_halt: + lw v0,pmax_rex_base + lw v0,REX_HALT(v0) + j v0 diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S --- v2.1.43/linux/arch/mips/lib/strlen_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/strlen_user.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,33 @@ +/* + * arch/mips/lib/strlen_user.S + * + * 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) 1996 by Ralf Baechle + */ +#include +#include +#include + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 for error + */ +LEAF(__strlen_user) + move v0,zero +1: lb t0,(a0) + LONG_ADDIU v0,1 + LONG_ADDIU a0,1 + bnez t0,1b + jr ra + END(__strlen_user) + + .section __ex_table,"a" + PTR 1b,fault + .previous + +fault: move v0,zero + jr ra diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S --- v2.1.43/linux/arch/mips/lib/strncpy_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/strncpy_user.S Thu Jun 26 12:33:37 1997 @@ -0,0 +1,48 @@ +/* + * arch/mips/lib/strncpy_user.S + * + * 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) 1996 by Ralf Baechle + */ +#include + +#include +#include + +/* + * Returns: -EFAULT if exception before terminator, N if the entire + * buffer filled, else strlen. + */ + +/* + * Ugly special case have to check: we might get passed a user space + * pointer which wraps into the kernel space ... + */ + +LEAF(__strncpy_from_user) + move v0,zero + move v1,a1 + .set noreorder +1: lbu t0,(v1) + LONG_ADDIU v1,1 + beqz t0,2f + sb t0,(a0) # delay slot + LONG_ADDIU v0,1 + bne v0,a2,1b + LONG_ADDIU a0,1 # delay slot + .set reorder +2: LONG_ADDU t0,a1,v0 + xor t0,a1 + bltz t0,fault + jr ra # return n + END(__strncpy_from_user) + +fault: li v0,-EFAULT + jr ra + + .section __ex_table,"a" + PTR 1b,fault + .previous diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/tags.c linux/arch/mips/lib/tags.c --- v2.1.43/linux/arch/mips/lib/tags.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/tags.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,75 @@ +/* + * linux/arch/mips/lib/tags.c + * + * Copyright (C) 1996 Stoned Elipot + */ +#include +#include +#include +#include +#include + +/* + * Parse the tags present in upper memory to find out + * a pecular one. + * + * Parameter: type - tag type to find + * + * returns : NULL - failure + * !NULL - pointer on the tag structure found + */ +tag * +bi_TagFind(enum bi_tag type) +{ + tag* t = (tag*)(mips_memory_upper - sizeof(tag)); + + while((t->tag != tag_dummy) && (t->tag != type)) + t = (tag*)(NEXTTAGPTR(t)); + + if (t->tag == tag_dummy) /* tag not found */ + return (tag*)NULL; + + return t; +} + +/* + * Snarf from the tag list in memory end some tags needed + * before the kernel reachs setup_arch() + * + * add yours here if you want to, but *beware*: the kernel var + * that will hold the values you want to snarf have to be + * in .data section of the kernel, so initialized in to whatever + * value in the kernel's sources. + */ +void bi_EarlySnarf(void) +{ + tag* atag; + + /* for wire_mappings() */ + atag = bi_TagFind(tag_machgroup); + if (atag) + memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); + else { + /* useless for boxes without text video mode but....*/ + panic("machine group not specified by bootloader"); + } + + atag = bi_TagFind(tag_machtype); + if (atag) + memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); + else { + /* useless for boxes without text video mode but....*/ + panic("machine type not specified by bootloader"); + } + + /* for tlbflush() */ + atag = bi_TagFind(tag_tlb_entries); + if (atag) + memcpy(&mips_tlb_entries, TAGVALPTR(atag), atag->size); + else { + /* useless for boxes without text video mode but....*/ + panic("number of TLB entries not specified by bootloader"); + } + + return; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/lib/tinycon.c linux/arch/mips/lib/tinycon.c --- v2.1.43/linux/arch/mips/lib/tinycon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/tinycon.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,133 @@ +/* + * arch/mips/lib/console.c + * + * Copyright (C) 1994 by Waldorf Electronic, + * written by Ralf Baechle and Andreas Busse + * + * 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. + * + * FIXME: This file is hacked to be hardwired for the Deskstation + * Only thought as a debugging console output. It's as inefficient + * as a piece of code can be but probably a good piece of code to + * implement a preliminary console for a new target. + */ + +#include +#include + +static unsigned int size_x; +static unsigned int size_y; +static unsigned short cursor_x; +static unsigned short cursor_y; +static volatile unsigned short *vram_addr; +static int console_needs_init = 1; + +extern struct screen_info screen_info; + +/* ---------------------------------------------------------------------- + * init_console() + * ---------------------------------------------------------------------- */ + +void init_console(void) +{ + size_x = 80; + size_y = 25; + cursor_x = 0; + cursor_y = 0; + + vram_addr = (unsigned short *)0xb00b8000; + + console_needs_init = 0; +} + +void +set_size_x(unsigned int x) +{ + size_x = x; +} + +void +set_size_y(unsigned int y) +{ + size_y = y; +} + +void +set_vram(unsigned short *vram) +{ + vram_addr = vram; +} + +void +set_crsr(unsigned int x, unsigned int y) +{ + cursor_x = x; + cursor_y = y; +} + +void +print_char(unsigned int x, unsigned int y, unsigned char c) +{ + volatile unsigned short *caddr; + + caddr = vram_addr + (y * size_x) + x; + *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c; +} + +static void +scroll(void) +{ + volatile unsigned short *caddr; + register int i; + + caddr = vram_addr; + for(i=0; i +#include +#include + + .set noreorder +/* + * Parameter: a0 - logic address to watch + * Currently only KSEG0 addresses are allowed! + * a1 - set bit #1 to trap on load references + * bit #0 to trap on store references + * Results : none + */ + LEAF(__watch_set) + li t0,0x80000000 + subu a0,t0 + ori a0,7 + xori a0,7 + or a0,a1 + mtc0 a0,CP0_WATCHLO + sw a0,watch_savelo + + jr ra + mtc0 zero,CP0_WATCHHI + END(__watch_set) + +/* + * Parameter: none + * Results : none + */ + LEAF(__watch_clear) + jr ra + mtc0 zero,CP0_WATCHLO + END(__watch_clear) + +/* + * Parameter: none + * Results : none + */ + LEAF(__watch_reenable) + lw t0,watch_savelo + + jr ra + mtc0 t0,CP0_WATCHLO + END(__watch_reenable) + +/* + * Saved value of the c0_watchlo register for watch_reenable() + */ + .data +watch_savelo: .word 0 + .text + +/* + * The stuff below are just some kernel debugging gadgets. It is only here + * because it had to be somewhere and will go away. + */ + +/* + * Parameter: none + * Results : none + */ + LEAF(get_sp) + jr ra + move v0,sp + END(get_sp) + +/* + * Parameter: none + * Results : none + */ + LEAF(get_ra) + jr ra + move v0,ra + END(get_ra) + +/* + * Parameter: none + * Results : none + */ + LEAF(get_status) + jr ra + mfc0 v0,CP0_STATUS + END(get_status) + +/* + * Parameter: none + * Results : none + */ + NESTED(print_sp, ((5*SZREG)+ALSZ)&ALMASK, sp) + .mask 0x80000000,4*SZREG + PTR_SUBU sp,((5*SZREG)+ALSZ)&ALMASK + REG_S ra,4*SZREG(sp) + move a1,sp + PRINT("$sp == %08lx\n") + REG_L ra,4*SZREG(sp) + + jr ra + PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK + END(print_sp) + +/* + * Parameter: none + * Results : none + */ + NESTED(print_st, ((5*SZREG)+ALSZ)&ALMASK, sp) + .mask 0x80000000,4*SZREG + PTR_SUBU sp,((5*SZREG)+ALSZ)&ALMASK + REG_S ra,4*SZREG(sp) + mfc0 a1,CP0_STATUS + PRINT("cp0_status == %08lx\n") + REG_L ra,4*SZREG(sp) + + jr ra + PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK + END(print_st) diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.1.43/linux/arch/mips/mm/Makefile Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/mm/Makefile Thu Jun 26 12:33:37 1997 @@ -8,6 +8,7 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := fault.o init.o +O_OBJS := extable.o init.o fault.o r4xx0.o r2300.o r6000.o tfp.o \ + andes.o loadmmu.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.1.43/linux/arch/mips/mm/andes.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/andes.c Thu Jun 26 12:33:37 1997 @@ -0,0 +1,101 @@ +/* $Id: andes.c,v 1.1 1997/06/06 09:34:31 ralf Exp $ + * andes.c: MMU and cache operations for the R10000 (ANDES). + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include + +#include +#include +#include +#include + +extern unsigned long mips_tlb_entries; + +/* Cache operations. XXX Write these dave... */ +static inline void andes_flush_cache_all(void) +{ + /* XXX */ +} + +static void andes_flush_cache_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void andes_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void andes_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + /* XXX */ +} + +static void andes_flush_page_to_ram(unsigned long page) +{ + /* XXX */ +} + +static void andes_flush_cache_sigtramp(unsigned long page) +{ + /* XXX */ +} + +/* TLB operations. XXX Write these dave... */ +static inline void andes_flush_tlb_all(void) +{ + /* XXX */ +} + +static void andes_flush_tlb_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void andes_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + /* XXX */ +} + +static void andes_load_pgd(unsigned long pg_dir) +{ +} + +static void andes_pgd_init(unsigned long page) +{ +} + +void ld_mmu_andes(void) +{ + flush_cache_all = andes_flush_cache_all; + flush_cache_mm = andes_flush_cache_mm; + flush_cache_range = andes_flush_cache_range; + flush_cache_page = andes_flush_cache_page; + flush_cache_sigtramp = andes_flush_cache_sigtramp; + flush_page_to_ram = andes_flush_page_to_ram; + + flush_tlb_all = andes_flush_tlb_all; + flush_tlb_mm = andes_flush_tlb_mm; + flush_tlb_range = andes_flush_tlb_range; + flush_tlb_page = andes_flush_tlb_page; + + load_pgd = andes_load_pgd; + pgd_init = andes_pgd_init; + + flush_cache_all(); + flush_tlb_all(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/extable.c linux/arch/mips/mm/extable.c --- v2.1.43/linux/arch/mips/mm/extable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/extable.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,54 @@ +/* + * linux/arch/mips/mm/extable.c + */ +#include +#include +#include + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; + +static inline unsigned +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid->nextinsn; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return 0; +} + +unsigned long +search_exception_table(unsigned long addr) +{ + unsigned long ret; + +#ifndef CONFIG_MODULES + /* There is only the kernel to search. */ + ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); + if (ret) return ret; +#else + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + for (mp = module_list; mp != NULL; mp = mp->next) { + if (mp->ex_table_start == NULL) + continue; + ret = search_one_table(mp->ex_table_start, + mp->ex_table_end - 1, addr); + if (ret) return ret; + } +#endif + + return 0; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.1.43/linux/arch/mips/mm/fault.c Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/mm/fault.c Thu Jun 26 12:33:38 1997 @@ -1,7 +1,7 @@ /* * arch/mips/mm/fault.c * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle */ #include #include @@ -13,29 +13,43 @@ #include #include #include +#include +#include -#include -#include #include +#include +#include +#include extern void die_if_kernel(char *, struct pt_regs *, long); +unsigned long asid_cache = ASID_FIRST_VERSION; + +/* + * Macro for exception fixup code to access integer registers. + */ +#define dpf_reg(r) (regs->regs[r]) + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void -do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, + unsigned long address) { struct vm_area_struct * vma; + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + unsigned long fixup; + lock_kernel(); #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); + printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, + address, writeaccess, regs->cp0_epc); #endif - vma = find_vma(current, address); + down(&mm->mmap_sem); + vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) @@ -56,29 +70,55 @@ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - handle_mm_fault(vma, address, writeaccess); - /* FIXME: This flushes the cache far to often */ - sys_cacheflush(address, PAGE_SIZE, BCACHE); + handle_mm_fault(tsk, vma, address, writeaccess); + up(&mm->mmap_sem); - return; + goto out; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ bad_area: + up(&mm->mmap_sem); + /* Did we have an exception handler installed? */ + + fixup = search_exception_table(regs->cp0_epc); + if (fixup) { + long new_epc; + new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", + regs->cp0_epc, new_epc); + regs->cp0_epc = new_epc; + goto out; + } + if (user_mode(regs)) { + tsk->tss.cp0_badvaddr = address; + tsk->tss.error_code = writeaccess; +#if 1 + printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n" + "%08lx (epc == %08lx, ra == %08lx)\n", + tsk->comm, + writeaccess ? "writeaccess to" : "readaccess from", + address, + (unsigned long) regs->cp0_epc, + (unsigned long) regs->regs[31]); +#endif + current->tss.cp0_badvaddr = address; current->tss.error_code = writeaccess; - send_sig(SIGSEGV, current, 1); - return; + force_sig(SIGSEGV, tsk); + goto out; } /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ printk(KERN_ALERT "Unable to handle kernel paging request at virtual " - "address %08lx\n", address); + "address %08lx, epc == %08lx\n", address, regs->cp0_epc); die_if_kernel("Oops", regs, writeaccess); do_exit(SIGKILL); +out: + unlock_kernel(); } diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.1.43/linux/arch/mips/mm/init.c Mon Apr 14 16:28:06 1997 +++ linux/arch/mips/mm/init.c Thu Jun 26 12:33:38 1997 @@ -15,26 +15,39 @@ #include #include #include +#include +#ifdef CONFIG_BLK_DEV_INITRD +#include +#endif +#include #include +#include #include #include #include -#include #include +#ifdef CONFIG_SGI +#include +#endif extern void deskstation_tyne_dma_init(void); -extern void sound_mem_init(void); -extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); -extern char empty_zero_page[PAGE_SIZE]; +const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; + +asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) +{ + /* XXX Just get it working for now... */ + flush_cache_all(); + return 0; +} /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving an inode + * for a process dying in kernel mode, possibly leaving a inode * unused etc.. * * BAD_PAGETABLE is the accompanying page-table: it is initialized @@ -48,9 +61,17 @@ extern char empty_bad_page_table[PAGE_SIZE]; unsigned long page; unsigned long dummy1, dummy2; +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) + unsigned long dummy3; +#endif - page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET); -#if __mips__ >= 3 + page = (unsigned long) empty_bad_page_table; + /* + * As long as we only save the low 32 bit of the 64 bit wide + * R4000 registers on interrupt we cannot use 64 bit memory accesses + * to the main memory. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) /* * Use 64bit code even for Linux/MIPS 32bit on R4000 */ @@ -69,11 +90,12 @@ ".set\tat\n" ".set\treorder" :"=r" (dummy1), - "=r" (dummy2) - :"r" (pte_val(BAD_PAGE)), - "0" (page), - "1" (PAGE_SIZE/8)); -#else + "=r" (dummy2), + "=r" (dummy3) + :"0" (page), + "1" (PAGE_SIZE/8), + "2" (pte_val(BAD_PAGE))); +#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */ __asm__ __volatile__( ".set\tnoreorder\n" "1:\tsw\t%2,(%0)\n\t" @@ -96,7 +118,7 @@ { unsigned long dummy1, dummy2; -#ifdef __R4000__ +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) /* * Use 64bit code even for Linux/MIPS 32bit on R4000 */ @@ -115,7 +137,7 @@ "=r" (dummy2) :"0" (page), "1" (PAGE_SIZE/8)); -#else +#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */ __asm__ __volatile__( ".set\tnoreorder\n" "1:\tsw\t$0,(%0)\n\t" @@ -133,9 +155,9 @@ static inline void zeropage(unsigned long page) { - sys_cacheflush((void *)page, PAGE_SIZE, BCACHE); + flush_page_to_ram(page); sync_mem(); - __zeropage(page + (PT_OFFSET - PAGE_OFFSET)); + __zeropage(page); } pte_t __bad_page(void) @@ -147,54 +169,6 @@ return pte_mkdirty(mk_pte(page, PAGE_SHARED)); } -unsigned long __zero_page(void) -{ - unsigned long page = (unsigned long) empty_zero_page; - - zeropage(page); - return 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 its contents we can avoid the writeback reading of - * the page. Speeds up the standard case a lot. - */ - __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; @@ -203,10 +177,10 @@ printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT; + i = max_mapnr; while (i-- > 0) { total++; - if (mem_map[i].reserved) + if (PageReserved(mem_map+i)) reserved++; else if (!atomic_read(&mem_map[i].count)) free++; @@ -227,7 +201,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) { - pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET)); + pgd_init((unsigned long)swapper_pg_dir); return free_area_init(start_mem, end_mem); } @@ -236,45 +210,75 @@ int codepages = 0; int datapages = 0; unsigned long tmp; - extern int _etext; + extern int _etext, _ftext; #ifdef CONFIG_MIPS_JAZZ - start_mem = vdma_init(start_mem, end_mem); + if (mips_machgroup == MACH_GROUP_JAZZ) + start_mem = vdma_init(start_mem, end_mem); #endif end_mem &= PAGE_MASK; - high_memory = end_mem; + max_mapnr = num_physpages = MAP_NR(end_mem); + high_memory = (void *)end_mem; + + /* clear the zero-page */ + memset(empty_zero_page, 0, PAGE_SIZE); /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); - tmp = start_mem; - while (tmp < high_memory) { - mem_map[MAP_NR(tmp)].reserved = 0; - tmp += PAGE_SIZE; - } + for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++) + clear_bit(PG_reserved, &mem_map[tmp].flags); + + /* + * For rPC44 and RM200 we've reserved some memory too much. Free + * the memory from PAGE_SIZE to PAGE_OFFSET + 0xa0000 again. We + * don't free the lowest page where the exception handlers will + * reside. + */ + if (mips_machgroup == MACH_GROUP_ARC && + mips_machtype == MACH_DESKSTATION_RPC44) + for(tmp = MAP_NR(PAGE_OFFSET + PAGE_SIZE); + tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++) + clear_bit(PG_reserved, &mem_map[tmp].flags); + + +#ifdef CONFIG_SGI + prom_fixup_mem_map(start_mem, (unsigned long)high_memory); +#endif #ifdef CONFIG_DESKSTATION_TYNE deskstation_tyne_dma_init(); #endif -#ifdef CONFIG_SOUND - sound_mem_init(); -#endif - for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) { - if (mem_map[MAP_NR(tmp)].reserved) { - if (tmp < (unsigned long) &_etext) + + for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) { + /* + * This is only for PC-style DMA. The onboard DMA + * of Jazz and Tyne machines is completly different and + * not handled via a flag in mem_map_t. + */ + if (tmp >= MAX_DMA_ADDRESS) + clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); + if (PageReserved(mem_map+MAP_NR(tmp))) { + if ((tmp < (unsigned long) &_etext) && + (tmp >= (unsigned long) &_ftext)) codepages++; - else if (tmp < start_mem) + else if ((tmp < start_mem) && + (tmp > (unsigned long) &_etext)) datapages++; continue; } atomic_set(&mem_map[MAP_NR(tmp)].count, 1); - free_page(tmp); +#ifdef CONFIG_BLK_DEV_INITRD + if (!initrd_start || (tmp < initrd_start || tmp >= + initrd_end)) +#endif + free_page(tmp); } tmp = nr_free_pages << PAGE_SHIFT; printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n", tmp >> 10, - (high_memory - PAGE_OFFSET) >> 10, + max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10)); @@ -290,13 +294,13 @@ { int i; - i = high_memory >> PAGE_SHIFT; + i = MAP_NR(high_memory); val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; val->bufferram = buffermem; while (i-- > 0) { - if (mem_map[i].reserved) + if (PageReserved(mem_map+i)) continue; val->totalram++; if (!atomic_read(&mem_map[i].count)) diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.1.43/linux/arch/mips/mm/loadmmu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/loadmmu.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,104 @@ +/* $Id: loadmmu.c,v 1.1 1997/06/06 09:34:51 ralf Exp $ + * loadmmu.c: Setup cpu/cache specific function ptrs at boot time. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* memory functions */ +void (*clear_page)(unsigned long page); +void (*copy_page)(unsigned long to, unsigned long from); + +/* Cache operations. */ +void (*flush_cache_all)(void); +void (*flush_cache_mm)(struct mm_struct *mm); +void (*flush_cache_range)(struct mm_struct *mm, unsigned long start, + unsigned long end); +void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); +void (*flush_cache_sigtramp)(unsigned long addr); +void (*flush_page_to_ram)(unsigned long page); + +/* TLB operations. */ +void (*flush_tlb_all)(void); +void (*flush_tlb_mm)(struct mm_struct *mm); +void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start, + unsigned long end); +void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); + +/* Miscellaneous. */ +void (*load_pgd)(unsigned long pg_dir); +void (*pgd_init)(unsigned long page); +void (*update_mmu_cache)(struct vm_area_struct * vma, + unsigned long address, pte_t pte); + +void (*show_regs)(struct pt_regs *); +asmlinkage void (*resume)(void *tsk); + +extern void ld_mmu_r2300(void); +extern void ld_mmu_r4xx0(void); +extern void ld_mmu_r6000(void); +extern void ld_mmu_tfp(void); +extern void ld_mmu_andes(void); + +void loadmmu(void) +{ + switch(mips_cputype) { + case CPU_R2000: + case CPU_R3000: + printk("Loading R[23]00 MMU routines.\n"); + ld_mmu_r2300(); + break; + + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4200: + case CPU_R4300: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R4600: + case CPU_R4640: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_R5000A: + printk("Loading R4000 MMU routines.\n"); + ld_mmu_r4xx0(); + break; + + case CPU_R6000: + case CPU_R6000A: + printk("Loading R6000 MMU routines.\n"); + ld_mmu_r6000(); + break; + + case CPU_R8000: + printk("Loading TFP MMU routines.\n"); + ld_mmu_tfp(); + break; + + case CPU_R10000: + printk("Loading R10000 MMU routines.\n"); + ld_mmu_andes(); + break; + + default: + /* XXX We need an generic routine in the MIPS port + * XXX to jabber stuff onto the screen on all machines + * XXX before the console is setup. The ARCS prom + * XXX routines look good for this, but only the SGI + * XXX code has a full library for that at this time. + */ + panic("Yeee, unsupported mmu/cache architecture."); + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.1.43/linux/arch/mips/mm/r2300.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/r2300.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,270 @@ +/* $Id: r2300.c,v 1.1 1997/06/06 09:35:14 ralf Exp $ + * r2300.c: R2000 and R3000 specific mmu/cache code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include + +#include +#include +#include +#include + +extern unsigned long mips_tlb_entries; + +/* page functions */ +void r2300_clear_page(unsigned long page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "addiu\t$1,%0,%2\n" + "1:\tsw\t$0,(%0)\n\t" + "sw\t$0,4(%0)\n\t" + "sw\t$0,8(%0)\n\t" + "sw\t$0,12(%0)\n\t" + "addiu\t%0,32\n\t" + "sw\t$0,-16(%0)\n\t" + "sw\t$0,-12(%0)\n\t" + "sw\t$0,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t$0,-4(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (page) + :"0" (page), + "I" (PAGE_SIZE) + :"$1","memory"); +} + +static void r2300_copy_page(unsigned long to, unsigned long from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "addiu\t$1,%0,%8\n" + "1:\tlw\t%2,(%1)\n\t" + "lw\t%3,4(%1)\n\t" + "lw\t%4,8(%1)\n\t" + "lw\t%5,12(%1)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%3,4(%0)\n\t" + "sw\t%4,8(%0)\n\t" + "sw\t%5,12(%0)\n\t" + "lw\t%2,16(%1)\n\t" + "lw\t%3,20(%1)\n\t" + "lw\t%4,24(%1)\n\t" + "lw\t%5,28(%1)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%3,20(%0)\n\t" + "sw\t%4,24(%0)\n\t" + "sw\t%5,28(%0)\n\t" + "addiu\t%0,64\n\t" + "addiu\t%1,64\n\t" + "lw\t%2,-32(%1)\n\t" + "lw\t%3,-28(%1)\n\t" + "lw\t%4,-24(%1)\n\t" + "lw\t%5,-20(%1)\n\t" + "sw\t%2,-32(%0)\n\t" + "sw\t%3,-28(%0)\n\t" + "sw\t%4,-24(%0)\n\t" + "sw\t%5,-20(%0)\n\t" + "lw\t%2,-16(%1)\n\t" + "lw\t%3,-12(%1)\n\t" + "lw\t%4,-8(%1)\n\t" + "lw\t%5,-4(%1)\n\t" + "sw\t%2,-16(%0)\n\t" + "sw\t%3,-12(%0)\n\t" + "sw\t%4,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t%5,-4(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), + "I" (PAGE_SIZE)); +} + +/* Cache operations. */ +static inline void r2300_flush_cache_all(void) { } +static void r2300_flush_cache_mm(struct mm_struct *mm) { } +static void r2300_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ +} + +static void r2300_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ +} + +static void r2300_flush_page_to_ram(unsigned long page) +{ + /* XXX What we want to do here is perform a displacement + * XXX flush because there are circumstances where you do + * XXX indeed want to remove stale data from the cache. + * XXX (DMA operations for example, where the cache cannot + * XXX "see" this data get changed.) + */ +} + +static void r2300_flush_cache_sigtramp(unsigned long page) +{ +} + +/* TLB operations. */ +static inline void r2300_flush_tlb_all(void) +{ + unsigned long flags; + int entry; + + save_flags(flags); cli(); + write_32bit_cp0_register(CP0_ENTRYLO0, 0); + for(entry = 0; entry < mips_tlb_entries; entry++) { + write_32bit_cp0_register(CP0_INDEX, entry); + write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x8) << 12)); + __asm__ __volatile__("tlbwi"); + } + restore_flags(flags); +} + +static void r2300_flush_tlb_mm(struct mm_struct *mm) +{ + if(mm == current->mm) + r2300_flush_tlb_all(); +} + +static void r2300_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + if(mm == current->mm) + r2300_flush_tlb_all(); +} + +static void r2300_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + if(vma->vm_mm == current->mm) + r2300_flush_tlb_all(); +} + +/* Load a new root pointer into the TLB. */ +static void r2300_load_pgd(unsigned long pg_dir) +{ + unsigned long flags; + + save_flags(flags); cli(); + write_32bit_cp0_register(CP0_ENTRYHI, TLB_ROOT); + write_32bit_cp0_register(CP0_INDEX, 0); + write_32bit_cp0_register(CP0_ENTRYLO0, ((pg_dir >> 6) | 0x00e0)); + __asm__ __volatile__("tlbwi"); + restore_flags(flags); +} + +/* + * Initialize new page directory with pointers to invalid ptes + */ +static void r2300_pgd_init(unsigned long page) +{ + unsigned long dummy1, dummy2; + + /* + * The plain and boring version for the R3000. No cache flushing + * stuff is implemented since the R3000 has physical caches. + */ + __asm__ __volatile__( + ".set\tnoreorder\n" + "1:\tsw\t%2,(%0)\n\t" + "sw\t%2,4(%0)\n\t" + "sw\t%2,8(%0)\n\t" + "sw\t%2,12(%0)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%2,20(%0)\n\t" + "sw\t%2,24(%0)\n\t" + "sw\t%2,28(%0)\n\t" + "subu\t%1,1\n\t" + "bnez\t%1,1b\n\t" + "addiu\t%0,32\n\t" + ".set\treorder" + :"=r" (dummy1), + "=r" (dummy2) + :"r" ((unsigned long) invalid_pte_table), + "0" (page), + "1" (PAGE_SIZE/(sizeof(pmd_t)*8))); +} + +static void r2300_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + r2300_flush_tlb_page(vma, address); + /* + * FIXME: We should also reload a new entry into the TLB to + * avoid unnecessary exceptions. + */ +} + +static void r2300_show_regs(struct pt_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], + (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], + (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], + (unsigned long) regs->regs[7]); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], + (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], + (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], + (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], + (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], + (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], + (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], + (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], + (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08x\nCause : %08x\n", + (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status, + (unsigned int) regs->cp0_cause); +} + +void ld_mmu_r2300(void) +{ + clear_page = r2300_clear_page; + copy_page = r2300_copy_page; + + flush_cache_all = r2300_flush_cache_all; + flush_cache_mm = r2300_flush_cache_mm; + flush_cache_range = r2300_flush_cache_range; + flush_cache_page = r2300_flush_cache_page; + flush_cache_sigtramp = r2300_flush_cache_sigtramp; + flush_page_to_ram = r2300_flush_page_to_ram; + + flush_tlb_all = r2300_flush_tlb_all; + flush_tlb_mm = r2300_flush_tlb_mm; + flush_tlb_range = r2300_flush_tlb_range; + flush_tlb_page = r2300_flush_tlb_page; + + load_pgd = r2300_load_pgd; + pgd_init = r2300_pgd_init; + update_mmu_cache = r2300_update_mmu_cache; + + show_regs = r2300_show_regs; + + flush_tlb_all(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.1.43/linux/arch/mips/mm/r4xx0.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/r4xx0.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,2445 @@ +/* + * r4xx0.c: R4000 processor variant specific MMU/Cache routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +/* Primary cache parameters. */ +static int icache_size, dcache_size; /* Size in bytes */ +static int ic_lsize, dc_lsize; /* LineSize in bytes */ + +/* Secondary cache (if present) parameters. */ +static scache_size, sc_lsize; /* Again, in bytes */ + +#include +#include + +#undef DEBUG_CACHE + +/* + * Zero an entire page. + */ + +static void r4k_clear_page_d16(unsigned long page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "cache\t%3,16(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "cache\t%3,-16(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (page) + :"0" (page), + "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D) + :"$1","memory"); +} + +static void r4k_clear_page_d32(unsigned long page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (page) + :"0" (page), + "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D) + :"$1","memory"); +} + + +/* + * This is still inefficient. We only can do better if we know the + * virtual address where the copy will be accessed. + */ + +static void r4k_copy_page_d16(unsigned long to, unsigned long from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tcache\t%9,(%0)\n\t" + "lw\t%2,(%1)\n\t" + "lw\t%3,4(%1)\n\t" + "lw\t%4,8(%1)\n\t" + "lw\t%5,12(%1)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%3,4(%0)\n\t" + "sw\t%4,8(%0)\n\t" + "sw\t%5,12(%0)\n\t" + "cache\t%9,16(%0)\n\t" + "lw\t%2,16(%1)\n\t" + "lw\t%3,20(%1)\n\t" + "lw\t%4,24(%1)\n\t" + "lw\t%5,28(%1)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%3,20(%0)\n\t" + "sw\t%4,24(%0)\n\t" + "sw\t%5,28(%0)\n\t" + "cache\t%9,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "lw\t%2,-32(%1)\n\t" + "lw\t%3,-28(%1)\n\t" + "lw\t%4,-24(%1)\n\t" + "lw\t%5,-20(%1)\n\t" + "sw\t%2,-32(%0)\n\t" + "sw\t%3,-28(%0)\n\t" + "sw\t%4,-24(%0)\n\t" + "sw\t%5,-20(%0)\n\t" + "cache\t%9,-16(%0)\n\t" + "lw\t%2,-16(%1)\n\t" + "lw\t%3,-12(%1)\n\t" + "lw\t%4,-8(%1)\n\t" + "lw\t%5,-4(%1)\n\t" + "sw\t%2,-16(%0)\n\t" + "sw\t%3,-12(%0)\n\t" + "sw\t%4,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t%5,-4(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), + "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); +} + +static void r4k_copy_page_d32(unsigned long to, unsigned long from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tcache\t%9,(%0)\n\t" + "lw\t%2,(%1)\n\t" + "lw\t%3,4(%1)\n\t" + "lw\t%4,8(%1)\n\t" + "lw\t%5,12(%1)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%3,4(%0)\n\t" + "sw\t%4,8(%0)\n\t" + "sw\t%5,12(%0)\n\t" + "lw\t%2,16(%1)\n\t" + "lw\t%3,20(%1)\n\t" + "lw\t%4,24(%1)\n\t" + "lw\t%5,28(%1)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%3,20(%0)\n\t" + "sw\t%4,24(%0)\n\t" + "sw\t%5,28(%0)\n\t" + "cache\t%9,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "lw\t%2,-32(%1)\n\t" + "lw\t%3,-28(%1)\n\t" + "lw\t%4,-24(%1)\n\t" + "lw\t%5,-20(%1)\n\t" + "sw\t%2,-32(%0)\n\t" + "sw\t%3,-28(%0)\n\t" + "sw\t%4,-24(%0)\n\t" + "sw\t%5,-20(%0)\n\t" + "lw\t%2,-16(%1)\n\t" + "lw\t%3,-12(%1)\n\t" + "lw\t%4,-8(%1)\n\t" + "lw\t%5,-4(%1)\n\t" + "sw\t%2,-16(%0)\n\t" + "sw\t%3,-12(%0)\n\t" + "sw\t%4,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t%5,-4(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), + "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); +} + +/* + * If you think for one second that this stuff coming up is a lot + * of bulky code eating too many kernel cache lines. Think _again_. + * + * Consider: + * 1) Taken branches have a 3 cycle penalty on R4k + * 2) The branch itself is a real dead cycle on even R4600/R5000. + * 3) Only one of the following variants of each type is even used by + * the kernel based upon the cache parameters we detect at boot time. + * + * QED. + */ + +static inline void r4k_flush_cache_all_s16d16i16(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); blast_scache16(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s32d16i16(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); blast_scache32(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s64d16i16(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); blast_scache64(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s128d16i16(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); blast_scache128(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s16d32i32(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); blast_scache16(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s32d32i32(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); blast_scache32(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s64d32i32(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); blast_scache64(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_s128d32i32(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); blast_scache128(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_d16i16(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); + restore_flags(flags); +} + +static inline void r4k_flush_cache_all_d32i32(void) +{ + unsigned long flags; + + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); + restore_flags(flags); +} + +static void +r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s16d16i16(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache16_page(start); + if(text) + blast_icache16_page(start); + blast_scache16_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void +r4k_flush_cache_range_s32d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s32d16i16(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache16_page(start); + if(text) + blast_icache16_page(start); + blast_scache32_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s64d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s64d16i16(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache16_page(start); + if(text) + blast_icache16_page(start); + blast_scache64_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s128d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s128d16i16(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache16_page(start); + if(text) + blast_icache16_page(start); + blast_scache128_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s16d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s16d32i32(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache32_page(start); + if(text) + blast_icache32_page(start); + blast_scache16_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s32d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s32d32i32(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache32_page(start); + if(text) + blast_icache32_page(start); + blast_scache32_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s64d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s64d32i32(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache32_page(start); + if(text) + blast_icache32_page(start); + blast_scache64_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_s128d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *vma; + unsigned long flags; + + if(mm->context == 0) + return; + + start &= PAGE_MASK; +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + vma = find_vma(mm, start); + if(vma) { + if(mm->context != current->mm->context) { + r4k_flush_cache_all_s128d32i32(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int text; + + save_flags(flags); cli(); + text = vma->vm_flags & VM_EXEC; + while(start < end) { + pgd = pgd_offset(mm, start); + pmd = pmd_offset(pgd, start); + pte = pte_offset(pmd, start); + + if(pte_val(*pte) & _PAGE_VALID) { + blast_dcache32_page(start); + if(text) + blast_icache32_page(start); + blast_scache128_page(start); + } + start += PAGE_SIZE; + } + restore_flags(flags); + } + } +} + +static void r4k_flush_cache_range_d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + save_flags(flags); cli(); + blast_dcache16(); blast_icache16(); + restore_flags(flags); + } +} + +static void r4k_flush_cache_range_d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + save_flags(flags); cli(); + blast_dcache32(); blast_icache32(); + restore_flags(flags); + } +} + +/* + * On architectures like the Sparc, we could get rid of lines in + * the cache created only by a certain context, but on the MIPS + * (and actually certain Sparc's) we cannot. + */ +static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s16d16i16(); + } +} + +static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s32d16i16(); + } +} + +static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s64d16i16(); + } +} + +static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s128d16i16(); + } +} + +static void r4k_flush_cache_mm_s16d32i32(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s16d32i32(); + } +} + +static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s32d32i32(); + } +} + +static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s64d32i32(); + } +} + +static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_s128d32i32(); + } +} + +static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_d16i16(); + } +} + +static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + r4k_flush_cache_all_d32i32(); + } +} + +static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache16_page_indexed(page); + if(text) + blast_icache16_page_indexed(page); + blast_scache16_page_indexed(page); + } else { + blast_dcache16_page(page); + if(text) + blast_icache16_page(page); + blast_scache16_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache16_page_indexed(page); + if(text) + blast_icache16_page_indexed(page); + blast_scache32_page_indexed(page); + } else { + blast_dcache16_page(page); + if(text) + blast_icache16_page(page); + blast_scache32_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache16_page_indexed(page); + if(text) + blast_icache16_page_indexed(page); + blast_scache64_page_indexed(page); + } else { + blast_dcache16_page(page); + if(text) + blast_icache16_page(page); + blast_scache64_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache16_page_indexed(page); + if(text) + blast_icache16_page_indexed(page); + blast_scache128_page_indexed(page); + } else { + blast_dcache16_page(page); + if(text) + blast_icache16_page(page); + blast_scache128_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s16d32i32(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache32_page_indexed(page); + blast_scache16_page_indexed(page); + } else { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + blast_scache16_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache32_page_indexed(page); + blast_scache32_page_indexed(page); + } else { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + blast_scache32_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache32_page_indexed(page); + blast_scache64_page_indexed(page); + } else { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + blast_scache64_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm->context != current->mm->context) { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (scache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache32_page_indexed(page); + blast_scache128_page_indexed(page); + } else { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + blast_scache128_page(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_VALID)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if(mm == current->mm) { + blast_dcache16_page(page); + if(text) + blast_icache16_page(page); + } else { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + blast_dcache16_page_indexed(page); + blast_dcache16_page_indexed(page ^ 0x2000); + if(text) { + blast_icache16_page_indexed(page); + blast_icache16_page_indexed(page ^ 0x2000); + } + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_PRESENT)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + } else { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + blast_dcache32_page_indexed(page); + if(text) + blast_icache32_page_indexed(page); + } +out: + restore_flags(flags); +} + +static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int text; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + save_flags(flags); cli(); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_PRESENT)) + goto out; + + text = (vma->vm_flags & VM_EXEC); + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { + blast_dcache32_page(page); + if(text) + blast_icache32_page(page); + } else { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + blast_dcache32_page_indexed(page); + blast_dcache32_page_indexed(page ^ 0x2000); + if(text) { + blast_icache32_page_indexed(page); + blast_icache32_page_indexed(page ^ 0x2000); + } + } +out: + restore_flags(flags); +} + +/* If the addresses passed to these routines are valid, they are + * either: + * + * 1) In KSEG0, so we can do a direct flush of the page. + * 2) In KSEG2, and since every process can translate those + * addresses all the time in kernel mode we can do a direct + * flush. + * 3) In KSEG1, no flush necessary. + */ +static void r4k_flush_page_to_ram_s16d16i16(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache16_page(page); + blast_scache16_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s32d16i16(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache16_page(page); + blast_scache32_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s64d16i16(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache16_page(page); + blast_scache64_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s128d16i16(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache16_page(page); + blast_scache128_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s16d32i32(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache32_page(page); + blast_scache16_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s32d32i32(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache32_page(page); + blast_scache32_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s64d32i32(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache32_page(page); + blast_scache64_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_s128d32i32(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache32_page(page); + blast_scache128_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_d16i16(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache16_page(page); + restore_flags(flags); + } +} + +static void r4k_flush_page_to_ram_d32i32(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + save_flags(flags); cli(); + blast_dcache32_page(page); + restore_flags(flags); + } +} + +/* + * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Invalidate_D, + * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only + * operate correctly if the internal data cache refill buffer is empty. These + * CACHE instructions should be separated from any potential data cache miss + * by a load instruction to an uncached address to empty the response buffer." + * (Revision 2.0 device errata from IDT available on http://www.idt.com/ + * in .pdf format.) + */ +static void r4k_flush_page_to_ram_d32i32_r4600(unsigned long page) +{ + page &= PAGE_MASK; + if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { + unsigned long flags; + +#ifdef DEBUG_CACHE + /* #if 1 */ + printk("r4600_cram[%08lx]", page); +#endif + /* + * Workaround for R4600 bug. Explanation see above. + */ + *(volatile unsigned long *)KSEG1; + + save_flags(flags); cli(); + blast_dcache32_page(page); + blast_dcache32_page(page ^ 0x2000); +#ifdef CONFIG_SGI + { + unsigned long tmp1, tmp2; + /* + * SGI goo. Have to check this closer ... + */ + __asm__ __volatile__(" + .set noreorder + .set mips3 + li %0, 0x1 + dsll %0, 31 + or %0, %0, %2 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %0, %1 + daddu %1, %0, 0x0fe0 + li %2, 0x80 + mtc0 %2, $12 + nop; nop; nop; nop; +1: sw $0, 0(%0) + bltu %0, %1, 1b + daddu %0, 32 + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %3, $12 + nop; nop; nop; nop; + .set mips0 + .set reorder" + : "=&r" (tmp1), "=&r" (tmp2), + "=&r" (page), "=&r" (flags) + : "2" (page & 0x0007f000), "3" (flags)); + } +#endif /* CONFIG_SGI */ + } +} + +static void r4k_flush_cache_sigtramp(unsigned long addr) +{ + addr &= ~(dc_lsize - 1); + flush_dcache_line(addr); + flush_dcache_line(addr + dc_lsize); + flush_icache_line(addr); + flush_icache_line(addr + dc_lsize); +} + +#undef DEBUG_TLB +#undef DEBUG_TLBUPDATE + +#define NTLB_ENTRIES 48 /* Fixed on all R4XX0 variants... */ +#define NTLB_ENTRIES_HALF 24 /* Fixed on all R4XX0 variants... */ + +static inline void r4k_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + + save_flags(flags); cli(); + /* Save old context and create impossible VPN2 value */ + old_ctx = (get_entryhi() & 0xff); + set_entryhi(KSEG0); + set_entrylo0(0); + set_entrylo1(0); + BARRIER; + + entry = 0; + + /* Blast 'em all away. */ + while(entry < NTLB_ENTRIES) { + set_index(entry); + BARRIER; + tlb_write_indexed(); + BARRIER; + entry++; + } + BARRIER; + set_entryhi(old_ctx); + restore_flags(flags); +} + +static void r4k_flush_tlb_mm(struct mm_struct *mm) +{ + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", mm->context); +#endif + save_flags(flags); cli(); + get_new_mmu_context(mm, asid_cache); + if(mm == current->mm) + set_entryhi(mm->context & 0xff); + restore_flags(flags); + } +} + +static void r4k_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + if(mm->context != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), + start, end); +#endif + save_flags(flags); cli(); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if(size <= NTLB_ENTRIES_HALF) { + int oldpid = (get_entryhi() & 0xff); + int newpid = (mm->context & 0xff); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while(start < end) { + int idx; + + set_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = get_index(); + set_entrylo0(0); + set_entrylo1(0); + set_entryhi(KSEG0); + BARRIER; + if(idx < 0) + continue; + tlb_write_indexed(); + BARRIER; + } + set_entryhi(oldpid); + } else { + get_new_mmu_context(mm, asid_cache); + if(mm == current->mm) + set_entryhi(mm->context & 0xff); + } + restore_flags(flags); + } +} + +static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + if(vma->vm_mm->context != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); +#endif + newpid = (vma->vm_mm->context & 0xff); + page &= (PAGE_MASK << 1); + save_flags(flags); cli(); + oldpid = (get_entryhi() & 0xff); + set_entryhi(page | newpid); + BARRIER; + tlb_probe(); + BARRIER; + idx = get_index(); + set_entrylo0(0); + set_entrylo1(0); + set_entryhi(KSEG0); + if(idx < 0) + goto finish; + BARRIER; + tlb_write_indexed(); + + finish: + BARRIER; + set_entryhi(oldpid); + restore_flags(flags); + } +} + +/* Load a new root pointer into the TLB. */ +static void r4k_load_pgd(unsigned long pg_dir) +{ +} + +static void r4k_pgd_init(unsigned long page) +{ + unsigned long *p = (unsigned long *) page; + int i; + + for(i = 0; i < 1024; i+=8) { + p[i + 0] = (unsigned long) invalid_pte_table; + p[i + 1] = (unsigned long) invalid_pte_table; + p[i + 2] = (unsigned long) invalid_pte_table; + p[i + 3] = (unsigned long) invalid_pte_table; + p[i + 4] = (unsigned long) invalid_pte_table; + p[i + 5] = (unsigned long) invalid_pte_table; + p[i + 6] = (unsigned long) invalid_pte_table; + p[i + 7] = (unsigned long) invalid_pte_table; + } +} + +#ifdef DEBUG_TLBUPDATE +static unsigned long ehi_debug[NTLB_ENTRIES]; +static unsigned long el0_debug[NTLB_ENTRIES]; +static unsigned long el1_debug[NTLB_ENTRIES]; +#endif + +/* We will need multiple versions of update_mmu_cache(), one that just + * updates the TLB with the new pte(s), and another which also checks + * for the R4k "end of page" hardware bug and does the needy. + */ +static void r4k_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + pid = (get_entryhi() & 0xff); + +#ifdef DEBUG_TLB + if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", + (int) (vma->vm_mm->context & 0xff), pid); + } +#endif + + save_flags(flags); cli(); + address &= (PAGE_MASK << 1); + set_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + BARRIER; + tlb_probe(); + BARRIER; + pmdp = pmd_offset(pgdp, address); + idx = get_index(); + ptep = pte_offset(pmdp, address); + BARRIER; + set_entrylo0(pte_val(*ptep++) >> 6); + set_entrylo1(pte_val(*ptep) >> 6); + set_entryhi(address | (pid)); + BARRIER; + if(idx < 0) { + tlb_write_random(); +#if 0 + BARRIER; + printk("[MISS]"); +#endif + } else { + tlb_write_indexed(); +#if 0 + BARRIER; + printk("[HIT]"); +#endif + } +#if 0 + if(!strcmp(current->comm, "args")) { + printk("<"); + for(idx = 0; idx < NTLB_ENTRIES; idx++) { + BARRIER; + set_index(idx); BARRIER; + tlb_read(); BARRIER; + address = get_entryhi(); BARRIER; + if((address & 0xff) != 0) + printk("[%08lx]", address); + } + printk(">"); + } + BARRIER; +#endif + BARRIER; + set_entryhi(pid); + BARRIER; + restore_flags(flags); +} + +#if 0 +static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx; + + save_flags(flags); cli(); + address &= (PAGE_MASK << 1); + set_entryhi(address | (get_entryhi() & 0xff)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = get_index(); + ptep = pte_offset(pmdp, address); + set_entrylo0(pte_val(*ptep++) >> 6); + set_entrylo1(pte_val(*ptep) >> 6); + BARRIER; + if(idx < 0) + tlb_write_random(); + else + tlb_write_indexed(); + BARRIER; + restore_flags(flags); +} +#endif + +static void r4k_show_regs(struct pt_regs * regs) +{ + /* Saved main processor registers. */ + printk("$0 : %08lx %08lx %08lx %08lx\n", + 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); + printk("$4 : %08lx %08lx %08lx %08lx\n", + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); + printk("$8 : %08lx %08lx %08lx %08lx\n", + regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); + printk("$12: %08lx %08lx %08lx %08lx\n", + regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); + printk("$16: %08lx %08lx %08lx %08lx\n", + regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); + printk("$20: %08lx %08lx %08lx %08lx\n", + regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); + printk("$24: %08lx %08lx\n", + regs->regs[24], regs->regs[25]); + printk("$28: %08lx %08lx %08lx %08lx\n", + regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); + + /* Saved cp0 registers. */ + printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", + regs->cp0_epc, regs->cp0_status, regs->cp0_cause); +} + +/* Detect and size the various r4k caches. */ +static void probe_icache(unsigned long config) +{ + unsigned long tmp; + + tmp = (config >> 9) & 7; + icache_size = (1 << (12 + tmp)); + if((config >> 5) & 1) + ic_lsize = 32; + else + ic_lsize = 16; + + printk("Primary ICACHE %dK (linesize %d bytes)\n", + (int)(icache_size >> 10), (int)ic_lsize); +} + +static void probe_dcache(unsigned long config) +{ + unsigned long tmp; + + tmp = (config >> 6) & 7; + dcache_size = (1 << (12 + tmp)); + if((config >> 4) & 1) + dc_lsize = 32; + else + dc_lsize = 16; + + printk("Primary DCACHE %dK (linesize %d bytes)\n", + (int)(dcache_size >> 10), (int)dc_lsize); +} + +static int probe_scache_eeprom(unsigned long config) +{ +#ifdef CONFIG_SGI + volatile unsigned int *cpu_control; + unsigned short cmd = 0xc220; + unsigned long data = 0; + int i, n; + +#ifdef __MIPSEB__ + cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034); +#else + cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030); +#endif +#define DEASSERT(bit) (*(cpu_control) &= (~(bit))) +#define ASSERT(bit) (*(cpu_control) |= (bit)) +#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") + DEASSERT(SGIMC_EEPROM_PRE); + DEASSERT(SGIMC_EEPROM_SDATAO); + DEASSERT(SGIMC_EEPROM_SECLOCK); + DEASSERT(SGIMC_EEPROM_PRE); + DELAY; + ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); + for(i = 0; i < 11; i++) { + if(cmd & (1<<15)) + ASSERT(SGIMC_EEPROM_SDATAO); + else + DEASSERT(SGIMC_EEPROM_SDATAO); + DEASSERT(SGIMC_EEPROM_SECLOCK); + ASSERT(SGIMC_EEPROM_SECLOCK); + cmd <<= 1; + } + DEASSERT(SGIMC_EEPROM_SDATAO); + for(i = 0; i < (sizeof(unsigned short) * 8); i++) { + unsigned int tmp; + + DEASSERT(SGIMC_EEPROM_SECLOCK); + DELAY; + ASSERT(SGIMC_EEPROM_SECLOCK); + DELAY; + data <<= 1; + tmp = *cpu_control; + if(tmp & SGIMC_EEPROM_SDATAI) + data |= 1; + } + DEASSERT(SGIMC_EEPROM_SECLOCK); + DEASSERT(SGIMC_EEPROM_CSEL); + ASSERT(SGIMC_EEPROM_PRE); + ASSERT(SGIMC_EEPROM_SECLOCK); + data <<= PAGE_SHIFT; + printk("R4600/R5000 SCACHE size %dK ", (int) (data >> 10)); + switch(mips_cputype) { + case CPU_R4600: + case CPU_R4640: + sc_lsize = 32; + break; + + default: + sc_lsize = 128; + break; + } + printk("linesize %d bytes\n", sc_lsize); + scache_size = data; + if(data) { + unsigned long addr, tmp1, tmp2; + + /* Enable r4600/r5000 cache. But flush it first. */ + for(addr = KSEG0; addr < (KSEG0 + dcache_size); + addr += dc_lsize) + flush_dcache_line_indexed(addr); + for(addr = KSEG0; addr < (KSEG0 + icache_size); + addr += ic_lsize) + flush_icache_line_indexed(addr); + for(addr = KSEG0; addr < (KSEG0 + scache_size); + addr += sc_lsize) + flush_scache_line_indexed(addr); + + /* R5000 scache enable is in CP0 config, on R4600 variants + * the scache is enable by the memory mapped cache controller. + */ + if(mips_cputype == CPU_R5000) { + unsigned long config; + + config = read_32bit_cp0_register(CP0_CONFIG); + config |= 0x1000; + write_32bit_cp0_register(CP0_CONFIG, config); + } else { + /* This is really cool... */ + printk("Enabling R4600 SCACHE\n"); + __asm__ __volatile__(" + .set noreorder + .set mips3 + li %0, 0x1 + dsll %0, 31 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %1, %0 + mfc0 %2, $12 + nop; nop; nop; nop; + li %1, 0x80 + mtc0 %1, $12 + nop; nop; nop; nop; + sb $0, 0(%0) + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %2, $12 + nop; nop; nop; nop; + .set mips0 + .set reorder + " : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); + } + + return 1; + } else { + if(mips_cputype == CPU_R5000) + return -1; + else + return 0; + } +#else + /* + * XXX For now we don't panic and assume that existing chipset + * controlled caches are setup correnctly and are completly + * transparent. Works fine for those MIPS machines I know. + * Morituri the salutant ... + */ + return 0; + + panic("Cannot probe SCACHE on this machine."); +#endif +} + +/* If you even _breathe_ on this function, look at the gcc output + * and make sure it does not pop things on and off the stack for + * the cache sizing loop that executes in KSEG1 space or else + * you will crash and burn badly. You have been warned. + */ +static int probe_scache(unsigned long config) +{ + extern unsigned long stext; + unsigned long flags, addr, begin, end, pow2; + int tmp; + + tmp = ((config >> 17) & 1); + if(tmp) + return 0; + tmp = ((config >> 22) & 3); + switch(tmp) { + case 0: + sc_lsize = 16; + break; + case 1: + sc_lsize = 32; + break; + case 2: + sc_lsize = 64; + break; + case 3: + sc_lsize = 128; + break; + } + + begin = (unsigned long) &stext; + begin &= ~((4 * 1024 * 1024) - 1); + end = begin + (4 * 1024 * 1024); + + /* This is such a bitch, you'd think they would make it + * easy to do this. Away you daemons of stupidity! + */ + save_flags(flags); cli(); + + /* Fill each size-multiple cache line with a valid tag. */ + pow2 = (64 * 1024); + for(addr = begin; addr < end; addr = (begin + pow2)) { + unsigned long *p = (unsigned long *) addr; + __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ + pow2 <<= 1; + } + + /* Load first line with zero (therefore invalid) tag. */ + set_taglo(0); + set_taghi(0); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + __asm__ __volatile__("\n\t.set noreorder\n\t" + ".set mips3\n\t" + "cache 8, (%0)\n\t" + ".set mips0\n\t" + ".set reorder\n\t" : : "r" (begin)); + __asm__ __volatile__("\n\t.set noreorder\n\t" + ".set mips3\n\t" + "cache 9, (%0)\n\t" + ".set mips0\n\t" + ".set reorder\n\t" : : "r" (begin)); + __asm__ __volatile__("\n\t.set noreorder\n\t" + ".set mips3\n\t" + "cache 11, (%0)\n\t" + ".set mips0\n\t" + ".set reorder\n\t" : : "r" (begin)); + + /* Now search for the wrap around point. */ + pow2 = (128 * 1024); + tmp = 0; + for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) { + __asm__ __volatile__("\n\t.set noreorder\n\t" + ".set mips3\n\t" + "cache 7, (%0)\n\t" + ".set mips0\n\t" + ".set reorder\n\t" : : "r" (addr)); + __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ + if(!get_taglo()) + break; + pow2 <<= 1; + } + restore_flags(flags); + addr -= begin; + printk("Secondary cache sized at %dK linesize %d\n", (int) (addr >> 10), + sc_lsize); + scache_size = addr; + return 1; +} + +static void setup_noscache_funcs(void) +{ + switch(dc_lsize) { + case 16: + clear_page = r4k_clear_page_d16; + copy_page = r4k_copy_page_d16; + flush_cache_all = r4k_flush_cache_all_d16i16; + flush_cache_mm = r4k_flush_cache_mm_d16i16; + flush_cache_range = r4k_flush_cache_range_d16i16; + flush_cache_page = r4k_flush_cache_page_d16i16; + flush_page_to_ram = r4k_flush_page_to_ram_d16i16; + break; + case 32: + clear_page = r4k_clear_page_d32; + copy_page = r4k_copy_page_d32; + flush_cache_all = r4k_flush_cache_all_d32i32; + flush_cache_mm = r4k_flush_cache_mm_d32i32; + flush_cache_range = r4k_flush_cache_range_d32i32; + flush_cache_page = r4k_flush_cache_page_d32i32; + flush_page_to_ram = r4k_flush_page_to_ram_d32i32; + break; + } +} + +static void setup_scache_funcs(void) +{ + switch(sc_lsize) { + case 16: + switch(dc_lsize) { + case 16: + clear_page = r4k_clear_page_d16; + copy_page = r4k_copy_page_d16; + flush_cache_all = r4k_flush_cache_all_s16d16i16; + flush_cache_mm = r4k_flush_cache_mm_s16d16i16; + flush_cache_range = r4k_flush_cache_range_s16d16i16; + flush_cache_page = r4k_flush_cache_page_s16d16i16; + flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16; + break; + case 32: + clear_page = r4k_clear_page_d32; + copy_page = r4k_copy_page_d32; + flush_cache_all = r4k_flush_cache_all_s16d32i32; + flush_cache_mm = r4k_flush_cache_mm_s16d32i32; + flush_cache_range = r4k_flush_cache_range_s16d32i32; + flush_cache_page = r4k_flush_cache_page_s16d32i32; + flush_page_to_ram = r4k_flush_page_to_ram_s16d32i32; + break; + }; + break; + case 32: + switch(dc_lsize) { + case 16: + clear_page = r4k_clear_page_d16; + copy_page = r4k_copy_page_d16; + flush_cache_all = r4k_flush_cache_all_s32d16i16; + flush_cache_mm = r4k_flush_cache_mm_s32d16i16; + flush_cache_range = r4k_flush_cache_range_s32d16i16; + flush_cache_page = r4k_flush_cache_page_s32d16i16; + flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16; + break; + case 32: + clear_page = r4k_clear_page_d32; + copy_page = r4k_copy_page_d32; + flush_cache_all = r4k_flush_cache_all_s32d32i32; + flush_cache_mm = r4k_flush_cache_mm_s32d32i32; + flush_cache_range = r4k_flush_cache_range_s32d32i32; + flush_cache_page = r4k_flush_cache_page_s32d32i32; + flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32; + break; + }; + case 64: + switch(dc_lsize) { + case 16: + clear_page = r4k_clear_page_d16; + copy_page = r4k_copy_page_d16; + flush_cache_all = r4k_flush_cache_all_s64d16i16; + flush_cache_mm = r4k_flush_cache_mm_s64d16i16; + flush_cache_range = r4k_flush_cache_range_s64d16i16; + flush_cache_page = r4k_flush_cache_page_s64d16i16; + flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16; + break; + case 32: + clear_page = r4k_clear_page_d32; + copy_page = r4k_copy_page_d32; + flush_cache_all = r4k_flush_cache_all_s64d32i32; + flush_cache_mm = r4k_flush_cache_mm_s64d32i32; + flush_cache_range = r4k_flush_cache_range_s64d32i32; + flush_cache_page = r4k_flush_cache_page_s64d32i32; + flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32; + break; + }; + case 128: + switch(dc_lsize) { + case 16: + clear_page = r4k_clear_page_d16; + copy_page = r4k_copy_page_d16; + flush_cache_all = r4k_flush_cache_all_s128d16i16; + flush_cache_mm = r4k_flush_cache_mm_s128d16i16; + flush_cache_range = r4k_flush_cache_range_s128d16i16; + flush_cache_page = r4k_flush_cache_page_s128d16i16; + flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16; + break; + case 32: + clear_page = r4k_clear_page_d32; + copy_page = r4k_copy_page_d32; + flush_cache_all = r4k_flush_cache_all_s128d32i32; + flush_cache_mm = r4k_flush_cache_mm_s128d32i32; + flush_cache_range = r4k_flush_cache_range_s128d32i32; + flush_cache_page = r4k_flush_cache_page_s128d32i32; + flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32; + break; + }; + break; + } +} + +typedef int (*probe_func_t)(unsigned long); +static probe_func_t probe_scache_kseg1; + +void ld_mmu_r4xx0(void) +{ + unsigned long cfg = read_32bit_cp0_register(CP0_CONFIG); + int sc_present = 0; + + printk("CPU REVISION IS: %08x\n", read_32bit_cp0_register(CP0_PRID)); + + probe_icache(cfg); + probe_dcache(cfg); + + switch(mips_cputype) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: +try_again: + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); + sc_present = probe_scache_kseg1(cfg); + break; + + case CPU_R4600: + case CPU_R4640: + case CPU_R4700: + case CPU_R5000: + probe_scache_kseg1 = (probe_func_t) + (KSEG1ADDR(&probe_scache_eeprom)); + sc_present = probe_scache_eeprom(cfg); + + /* Try using tags if eeprom give us bogus data. */ + if(sc_present == -1) + goto try_again; + break; + }; + + if(!sc_present) { + /* Lacks secondary cache. */ + setup_noscache_funcs(); + } else { + /* Has a secondary cache. */ + if(mips_cputype != CPU_R4600 && + mips_cputype != CPU_R4640 && + mips_cputype != CPU_R4700 && + mips_cputype != CPU_R5000) { + setup_scache_funcs(); + } else { + setup_noscache_funcs(); + if((mips_cputype != CPU_R5000)) { + flush_cache_page = + r4k_flush_cache_page_d32i32_r4600; + flush_page_to_ram = + r4k_flush_page_to_ram_d32i32_r4600; + } + } + } + + flush_cache_sigtramp = r4k_flush_cache_sigtramp; + + flush_tlb_all = r4k_flush_tlb_all; + flush_tlb_mm = r4k_flush_tlb_mm; + flush_tlb_range = r4k_flush_tlb_range; + flush_tlb_page = r4k_flush_tlb_page; + + load_pgd = r4k_load_pgd; + pgd_init = r4k_pgd_init; + update_mmu_cache = r4k_update_mmu_cache; + + show_regs = r4k_show_regs; + + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + + /* + * You should never change this register: + * - On R4600 1.7 the tlbp never hits for pages smaller than + * the value in the c0_pagemask register. + * - The entire mm handling assumes the c0_pagemask register to + * be set for 4kb pages. + */ + write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); + flush_tlb_all(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c --- v2.1.43/linux/arch/mips/mm/r6000.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/r6000.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,181 @@ +/* $Id: r6000.c,v 1.1 1997/06/06 09:35:31 ralf Exp $ + * r6000.c: MMU and cache routines for the R6000 processors. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +__asm__(".set mips3"); /* because we know... */ + +/* Cache operations. XXX Write these dave... */ +static inline void r6000_flush_cache_all(void) +{ + /* XXX */ +} + +static void r6000_flush_cache_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void r6000_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void r6000_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + /* XXX */ +} + +static void r6000_flush_page_to_ram(unsigned long page) +{ + /* XXX */ +} + +static void r6000_flush_cache_sigtramp(unsigned long page) +{ + /* XXX */ +} + +/* TLB operations. XXX Write these dave... */ +static inline void r6000_flush_tlb_all(void) +{ + /* XXX */ +} + +static void r6000_flush_tlb_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void r6000_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void r6000_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + /* XXX */ +} + +static void r6000_load_pgd(unsigned long pg_dir) +{ +} + +static void r6000_pgd_init(unsigned long page) +{ + unsigned long dummy1, dummy2; + + /* + * This version is optimized for the R6000. We generate dirty lines + * in the datacache, overwrite these lines with zeros and then flush + * the cache. Sounds horribly complicated but is just a trick to + * avoid unnecessary loads of from memory and uncached stores which + * are very expensive. Not tested yet as the R6000 is a rare CPU only + * available in SGI machines and I don't have one. + */ + __asm__ __volatile__( + ".set\tnoreorder\n" + "1:\t" + "cache\t%5,(%0)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%2,4(%0)\n\t" + "sw\t%2,8(%0)\n\t" + "sw\t%2,12(%0)\n\t" + "cache\t%5,16(%0)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%2,20(%0)\n\t" + "sw\t%2,24(%0)\n\t" + "sw\t%2,28(%0)\n\t" + "subu\t%1,1\n\t" + "bnez\t%1,1b\n\t" + "addiu\t%0,32\n\t" + ".set\treorder" + :"=r" (dummy1), + "=r" (dummy2) + :"r" ((unsigned long) invalid_pte_table), + "0" (page), + "1" (PAGE_SIZE/(sizeof(pmd_t)*8)), + "i" (Create_Dirty_Excl_D)); +} + +static void r6000_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + r6000_flush_tlb_page(vma, address); + /* + * FIXME: We should also reload a new entry into the TLB to + * avoid unnecessary exceptions. + */ +} + +static void r6000_show_regs(struct pt_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], + (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], + (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], + (unsigned long) regs->regs[7]); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], + (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], + (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], + (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], + (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], + (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], + (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], + (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], + (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08x\nCause : %08x\n", + (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status, + (unsigned int) regs->cp0_cause); +} + +void ld_mmu_r6000(void) +{ + flush_cache_all = r6000_flush_cache_all; + flush_cache_mm = r6000_flush_cache_mm; + flush_cache_range = r6000_flush_cache_range; + flush_cache_page = r6000_flush_cache_page; + flush_cache_sigtramp = r6000_flush_cache_sigtramp; + flush_page_to_ram = r6000_flush_page_to_ram; + + flush_tlb_all = r6000_flush_tlb_all; + flush_tlb_mm = r6000_flush_tlb_mm; + flush_tlb_range = r6000_flush_tlb_range; + flush_tlb_page = r6000_flush_tlb_page; + + load_pgd = r6000_load_pgd; + pgd_init = r6000_pgd_init; + update_mmu_cache = r6000_update_mmu_cache; + + show_regs = r6000_show_regs; + + flush_cache_all(); + flush_tlb_all(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c --- v2.1.43/linux/arch/mips/mm/tfp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/tfp.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,102 @@ +/* $Id: tfp.c,v 1.1 1997/06/06 09:35:39 ralf Exp $ + * tfp.c: MMU and cache routines specific to the r8000 (TFP). + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include + +#include +#include +#include +#include + +extern unsigned long mips_tlb_entries; + +/* Cache operations. XXX Write these dave... */ +static inline void tfp_flush_cache_all(void) +{ + /* XXX */ +} + +static void tfp_flush_cache_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void tfp_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void tfp_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + /* XXX */ +} + +static void tfp_flush_page_to_ram(unsigned long page) +{ + /* XXX */ +} + +static void tfp_flush_cache_sigtramp(unsigned long page) +{ + /* XXX */ +} + +/* TLB operations. XXX Write these dave... */ +static inline void tfp_flush_tlb_all(void) +{ + /* XXX */ +} + +static void tfp_flush_tlb_mm(struct mm_struct *mm) +{ + /* XXX */ +} + +static void tfp_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + /* XXX */ +} + +static void tfp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + /* XXX */ +} + +static void tfp_load_pgd(unsigned long pg_dir) +{ +} + +static void tfp_pgd_init(unsigned long page) +{ +} + +void ld_mmu_tfp(void) +{ + flush_cache_all = tfp_flush_cache_all; + flush_cache_mm = tfp_flush_cache_mm; + flush_cache_range = tfp_flush_cache_range; + flush_cache_page = tfp_flush_cache_page; + flush_cache_sigtramp = tfp_flush_cache_sigtramp; + flush_page_to_ram = tfp_flush_page_to_ram; + + flush_tlb_all = tfp_flush_tlb_all; + flush_tlb_mm = tfp_flush_tlb_mm; + flush_tlb_range = tfp_flush_tlb_range; + flush_tlb_page = tfp_flush_tlb_page; + + load_pgd = tfp_load_pgd; + pgd_init = tfp_pgd_init; + + flush_cache_all(); + flush_tlb_all(); +} + diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile --- v2.1.43/linux/arch/mips/sgi/kernel/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/Makefile Thu Jun 26 12:33:38 1997 @@ -0,0 +1,30 @@ +# $Id: Makefile,v 1.1 1997/06/06 09:36:08 ralf Exp $ +# Makefile for the SGI specific kernel interface routines +# under Linux. +# +# 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) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +OBJS = indy_mc.o indy_hpc.o indy_int.o system.o indy_timer.o indyIRQ.o \ + reset.o setup.o time.o + +all: sgikern.a + +sgikern.a: $(OBJS) + $(AR) rcs sgikern.a $(OBJS) + sync + +indyIRQ.o: indyIRQ.S + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S --- v2.1.43/linux/arch/mips/sgi/kernel/indyIRQ.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indyIRQ.S Thu Jun 26 12:33:38 1997 @@ -0,0 +1,129 @@ +/* $Id: indyIRQ.S,v 1.1 1997/06/06 09:36:13 ralf Exp $ + * indyIRQ.S: Interrupt exception dispatch code for FullHouse and + * Guiness. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include + + /* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop + * and moving across all the pending IRQ bits in the cause + * register is _NOT_ the answer, the common case is one + * pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register + * IRQ mask, that would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs + * off, nothing in between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the INDY look basically (barring + * software IRQs which we don't use at all) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Local IRQ level zero + * 3 Local IRQ level one + * 4 8254 Timer zero + * 5 8254 Timer one + * 6 Bus Error + * 7 R4k timer (what we use) + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Local IRQ zero + * Local IRQ one + * Bus Error + * 8254 Timer zero + * Lowest ---- 8254 Timer one + * + * then we just return, if multiple IRQs are pending then + * we will just take another exception, big deal. + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(indyIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 s0, CP0_CAUSE # get irq mask + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero + + /* Wheee, a timer interrupt. */ + move a0, sp + addiu t0, s7, 1 + jal indy_timer_interrupt + nop # delay slot + + j ret_from_sys_call + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP3 # delay slot, check local level one + + /* Wheee, local level zero interrupt. */ + jal indy_local0_irqdispatch + move a0, sp # delay slot + + j ret_from_sys_call + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP6 # delay slot, check bus error + + /* Wheee, local level one interrupt. */ + move a0, sp + jal indy_local1_irqdispatch + nop + + j ret_from_sys_call + nop + +1: + beq a0, zero, 1f + nop + + /* Wheee, an asynchronous bus error... */ + move a0, sp + jal indy_buserror_irq + nop + + j ret_from_sys_call + nop + +1: + /* Here by mistake? This is possible, what can happen + * is that by the time we take the exception the IRQ + * pin goes low, so just leave if this is the case. + */ + andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) + beq a0, zero, 1f + addiu t0, s7, 1 + + /* Must be one of the 8254 timers... */ + move a0, sp + jal indy_8254timer_irq + nop +1: + j ret_from_sys_call + nop + END(indyIRQ) diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c --- v2.1.43/linux/arch/mips/sgi/kernel/indy_hpc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indy_hpc.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,114 @@ +/* $Id: indy_hpc.c,v 1.1 1997/06/06 09:36:18 ralf Exp $ + * indy_hpc.c: Routines for generic manipulation of the HPC controllers. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include + +/* #define DEBUG_SGIHPC */ + +struct hpc3_regs *hpc3c0, *hpc3c1; +struct hpc3_miscregs *hpc3mregs; + +/* We need software copies of these because they are write only. */ +static unsigned long write1, write2; + +/* Machine specific identifier knobs. */ +int sgi_has_ioc2 = 0; +int sgi_guiness = 0; +int sgi_boardid; + +void sgihpc_write1_modify(int set, int clear) +{ + write1 |= set; + write1 &= ~clear; + hpc3mregs->write1 = write1; +} + +void sgihpc_write2_modify(int set, int clear) +{ + write2 |= set; + write2 &= ~clear; + hpc3mregs->write2 = write2; +} + +void sgihpc_init(void) +{ + unsigned long sid, crev, brev; + + hpc3c0 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP0_PBASE); + hpc3c1 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP1_PBASE); + hpc3mregs = (struct hpc3_miscregs *) (KSEG1 + HPC3_MREGS_PBASE); + sid = hpc3mregs->sysid; + + sid &= 0xff; + crev = (sid & 0xe0) >> 5; + brev = (sid & 0x1e) >> 1; + +#ifdef DEBUG_SGIHPC + prom_printf("sgihpc_init: crev<%2x> brev<%2x>\n", crev, brev); + prom_printf("sgihpc_init: "); +#endif + + if(sid & 1) { +#ifdef DEBUG_SGIHPC + prom_printf("GUINESS "); +#endif + sgi_guiness = 1; + } else { +#ifdef DEBUG_SGIHPC + prom_printf("FULLHOUSE "); +#endif + sgi_guiness = 0; + } + sgi_boardid = brev; + +#ifdef DEBUG_SGIHPC + prom_printf("sgi_boardid<%d> ", sgi_boardid); +#endif + + if(crev == 1) { + if((sid & 1) || (brev >= 2)) { +#ifdef DEBUG_SGIHPC + prom_printf("IOC2 "); +#endif + sgi_has_ioc2 = 1; + } else { +#ifdef DEBUG_SGIHPC + prom_printf("IOC1 revision 1 "); +#endif + } + } else { +#ifdef DEBUG_SGIHPC + prom_printf("IOC1 revision 0 "); +#endif + } +#ifdef DEBUG_SGIHPC + prom_printf("\n"); +#endif + + write1 = (HPC3_WRITE1_PRESET | + HPC3_WRITE1_KMRESET | + HPC3_WRITE1_ERESET | + HPC3_WRITE1_LC0OFF); + + write2 = (HPC3_WRITE2_EASEL | + HPC3_WRITE2_NTHRESH | + HPC3_WRITE2_TPSPEED | + HPC3_WRITE2_EPSEL | + HPC3_WRITE2_U0AMODE | + HPC3_WRITE2_U1AMODE); + + if(!sgi_guiness) + write1 |= HPC3_WRITE1_GRESET; + hpc3mregs->write1 = write1; + hpc3mregs->write2 = write2; + + hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.1.43/linux/arch/mips/sgi/kernel/indy_int.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indy_int.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,600 @@ +/* $Id: indy_int.c,v 1.1 1997/06/06 09:36:21 ralf Exp $ + * indy_int.c: Routines for generic manipulation of the INT[23] ASIC + * found on INDY workstations.. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* #define DEBUG_SGINT */ + +struct sgi_int2_regs *sgi_i2regs; +struct sgi_int3_regs *sgi_i3regs; +struct sgi_ioc_ints *ioc_icontrol; +struct sgi_ioc_timers *ioc_timers; +volatile unsigned char *ioc_tclear; + +static char lc0msk_to_irqnr[256]; +static char lc1msk_to_irqnr[256]; +static char lc2msk_to_irqnr[256]; +static char lc3msk_to_irqnr[256]; + +extern asmlinkage void indyIRQ(void); + +#ifdef CONFIG_REMOTE_DEBUG +extern void rs_kgdb_hook(int); +#endif + +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +/* Local IRQ's are layed out logically like this: + * + * 0 --> 7 == local 0 interrupts + * 8 --> 15 == local 1 interrupts + * 16 --> 23 == vectored level 2 interrupts + * 24 --> 31 == vectored level 3 interrupts (not used) + */ +void disable_local_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_flags(flags); + cli(); + switch(irq_nr) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + ioc_icontrol->imask0 &= ~(1 << irq_nr); + break; + + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + ioc_icontrol->imask1 &= ~(1 << (irq_nr - 8)); + break; + + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + ioc_icontrol->cmeimask0 &= ~(1 << (irq_nr - 16)); + break; + + default: + /* This way we'll see if anyone would ever want vectored + * level 3 interrupts. Highly unlikely. + */ + printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); + panic("INVALID IRQ level!"); + }; + restore_flags(flags); +} + +void enable_local_irq(unsigned int irq_nr) +{ + unsigned long flags; + save_flags(flags); + cli(); + switch(irq_nr) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + ioc_icontrol->imask0 |= (1 << irq_nr); + break; + + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + ioc_icontrol->imask1 |= (1 << (irq_nr - 8)); + break; + + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + enable_local_irq(7); + ioc_icontrol->cmeimask0 |= (1 << (irq_nr - 16)); + break; + + default: + printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); + panic("INVALID IRQ level!"); + }; + restore_flags(flags); +} + +void disable_gio_irq(unsigned int irq_nr) +{ + /* XXX TODO XXX */ +} + +void enable_gio_irq(unsigned int irq_nr) +{ + /* XXX TODO XXX */ +} + +void disable_hpcdma_irq(unsigned int irq_nr) +{ + /* XXX TODO XXX */ +} + +void enable_hpcdma_irq(unsigned int irq_nr) +{ + /* XXX TODO XXX */ +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned int n = irq_nr; + if(n >= SGINT_END) { + printk("whee, invalid irq_nr %d\n", irq_nr); + panic("IRQ, you lose..."); + } + if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { + disable_local_irq(n - SGINT_LOCAL0); + } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { + disable_gio_irq(n - SGINT_GIO); + } else if(n >= SGINT_HPCDMA && n < SGINT_END) { + disable_hpcdma_irq(n - SGINT_HPCDMA); + } else { + panic("how did I get here?"); + } +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned int n = irq_nr; + if(n >= SGINT_END) { + printk("whee, invalid irq_nr %d\n", irq_nr); + panic("IRQ, you lose..."); + } + if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { + enable_local_irq(n - SGINT_LOCAL0); + } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { + enable_gio_irq(n - SGINT_GIO); + } else if(n >= SGINT_HPCDMA && n < SGINT_END) { + enable_hpcdma_irq(n - SGINT_HPCDMA); + } else { + panic("how did I get here?"); + } +} + +#if 0 +/* + * Currently unused. + */ +static void local_unex(int irq, void *data, struct pt_regs *regs) +{ + printk("Whee: unexpected local IRQ at %08lx\n", + (unsigned long) regs->cp0_epc); + printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>\n", + ioc_icontrol->istat0, ioc_icontrol->istat1, + ioc_icontrol->vmeistat); +} +#endif + +static struct irqaction *local_irq_action[24] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL +}; + +int setup_indy_irq(int irq, struct irqaction * new) +{ + printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s %p\n", + irq, new->name, new->handler); + return 0; +} + +static struct irqaction r4ktimer_action = { + NULL, 0, 0, "R4000 timer/counter", NULL, NULL, +}; + +static struct irqaction indy_berr_action = { + NULL, 0, 0, "IP22 Bus Error", NULL, NULL, +}; + +static struct irqaction *irq_action[16] = { + NULL, NULL, NULL, NULL, + NULL, NULL, &indy_berr_action, &r4ktimer_action, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + int num = 0; + struct irqaction * action; + + for (i = 0 ; i < 16 ; i++, num++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + num, kstat.interrupts[num], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, " [on-chip]\n"); + } + for (i = 0 ; i < 24 ; i++, num++) { + action = local_irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + num, kstat.interrupts[num], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, " [local]\n"); + } + return len; +} + +atomic_t __mips_bh_counter; + +#ifdef __SMP__ +#error Send superfluous SMP boxes to ralf@uni-koblenz.de +#else +#define irq_enter(cpu, irq) (++local_irq_count[cpu]) +#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#endif + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction * action = *(irq + irq_action); + + lock_kernel(); + kstat.interrupts[irq]++; + printk("Got irq %d, press a key.", irq); + prom_getchar(); + romvec->imode(); + while (action) { + if (action->flags & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + action->handler(irq, action->dev_id, regs); + action = action->next; + } + unlock_kernel(); +} + +/* + * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return + * stuff - the handler is also running with interrupts disabled unless + * it explicitly enables them later. + */ +asmlinkage void do_fast_IRQ(int irq) +{ + struct irqaction * action = *(irq + irq_action); + + lock_kernel(); + printk("Got irq %d, press a key.", irq); + prom_getchar(); + romvec->imode(); + kstat.interrupts[irq]++; + while (action) { + if (action->flags & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + action->handler(irq, action->dev_id, NULL); + action = action->next; + } + unlock_kernel(); +} + +int request_local_irq(unsigned int lirq, void (*func)(int, void *, struct pt_regs *), + unsigned long iflags, const char *dname, void *devid) +{ + struct irqaction *action; + + lirq -= SGINT_LOCAL0; + if(lirq >= 24 || !func) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if(!action) + return -ENOMEM; + + action->handler = func; + action->flags = iflags; + action->mask = 0; + action->name = dname; + action->dev_id = devid; + action->next = 0; + local_irq_action[lirq] = action; + enable_irq(lirq + SGINT_LOCAL0); + return 0; +} + +void free_local_irq(unsigned int lirq, void *dev_id) +{ + struct irqaction *action; + + lirq -= SGINT_LOCAL0; + if(lirq >= 24) { + printk("Aieee: trying to free bogus local irq %d\n", + lirq + SGINT_LOCAL0); + return; + } + action = local_irq_action[lirq]; + local_irq_action[lirq] = NULL; + disable_irq(lirq + SGINT_LOCAL0); + kfree(action); +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action; + + if (irq >= SGINT_END) + return -EINVAL; + if (!handler) + return -EINVAL; + + if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) + return request_local_irq(irq, handler, irqflags, devname, dev_id); + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_indy_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq >= SGINT_END) { + printk("Trying to free IRQ%d\n",irq); + return; + } + if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) { + free_local_irq(irq, dev_id); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_flags(flags); + cli(); + *p = action->next; + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +void init_IRQ(void) +{ + int i; + + for (i = 0; i < 16 ; i++) + set_int_vector(i, 0); + irq_setup(); +} + +void indy_local0_irqdispatch(struct pt_regs *regs) +{ + struct irqaction *action; + unsigned char mask = ioc_icontrol->istat0; + unsigned char mask2 = 0; + int irq; + + mask &= ioc_icontrol->imask0; + if(mask & ISTAT0_LIO2) { + mask2 = ioc_icontrol->vmeistat; + mask2 &= ioc_icontrol->cmeimask0; + irq = lc2msk_to_irqnr[mask2]; + action = local_irq_action[irq]; + } else { + irq = lc0msk_to_irqnr[mask]; + action = local_irq_action[irq]; + } +#if 0 + printk("local0_dispatch: got irq %d mask %2x mask2 %2x\n", + irq, mask, mask2); + prom_getchar(); +#endif + kstat.interrupts[irq + 16]++; + action->handler(irq, action->dev_id, regs); +} + +void indy_local1_irqdispatch(struct pt_regs *regs) +{ + struct irqaction *action; + unsigned char mask = ioc_icontrol->istat1; + unsigned char mask2 = 0; + int irq; + + mask &= ioc_icontrol->imask1; + if(mask & ISTAT1_LIO3) { + printk("WHee: Got an LIO3 irq, winging it...\n"); + mask2 = ioc_icontrol->vmeistat; + mask2 &= ioc_icontrol->cmeimask1; + irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat]; + action = local_irq_action[irq]; + } else { + irq = lc1msk_to_irqnr[mask]; + action = local_irq_action[irq]; + } +#if 0 + printk("local1_dispatch: got irq %d mask %2x mask2 %2x\n", + irq, mask, mask2); + prom_getchar(); +#endif + kstat.interrupts[irq + 24]++; + action->handler(irq, action->dev_id, regs); +} + +void indy_buserror_irq(struct pt_regs *regs) +{ + kstat.interrupts[6]++; + printk("Got a bus error IRQ, shouldn't happen yet\n"); + show_regs(regs); + printk("Spinning...\n"); + while(1) + ; +} + +/* Misc. crap just to keep the kernel linking... */ +unsigned long probe_irq_on (void) +{ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + return 0; +} + +void sgint_init(void) +{ + int i; +#ifdef CONFIG_REMOTE_DEBUG + char *ctype; +#endif + + sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE); + sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); + + /* Init local mask --> irq tables. */ + for(i = 0; i < 256; i++) { + if(i & 0x80) { + lc0msk_to_irqnr[i] = 7; + lc1msk_to_irqnr[i] = 15; + lc2msk_to_irqnr[i] = 23; + lc3msk_to_irqnr[i] = 31; + } else if(i & 0x40) { + lc0msk_to_irqnr[i] = 6; + lc1msk_to_irqnr[i] = 14; + lc2msk_to_irqnr[i] = 22; + lc3msk_to_irqnr[i] = 30; + } else if(i & 0x20) { + lc0msk_to_irqnr[i] = 5; + lc1msk_to_irqnr[i] = 13; + lc2msk_to_irqnr[i] = 21; + lc3msk_to_irqnr[i] = 29; + } else if(i & 0x10) { + lc0msk_to_irqnr[i] = 4; + lc1msk_to_irqnr[i] = 12; + lc2msk_to_irqnr[i] = 20; + lc3msk_to_irqnr[i] = 28; + } else if(i & 0x08) { + lc0msk_to_irqnr[i] = 3; + lc1msk_to_irqnr[i] = 11; + lc2msk_to_irqnr[i] = 19; + lc3msk_to_irqnr[i] = 27; + } else if(i & 0x04) { + lc0msk_to_irqnr[i] = 2; + lc1msk_to_irqnr[i] = 10; + lc2msk_to_irqnr[i] = 18; + lc3msk_to_irqnr[i] = 26; + } else if(i & 0x02) { + lc0msk_to_irqnr[i] = 1; + lc1msk_to_irqnr[i] = 9; + lc2msk_to_irqnr[i] = 17; + lc3msk_to_irqnr[i] = 25; + } else if(i & 0x01) { + lc0msk_to_irqnr[i] = 0; + lc1msk_to_irqnr[i] = 8; + lc2msk_to_irqnr[i] = 16; + lc3msk_to_irqnr[i] = 24; + } else { + lc0msk_to_irqnr[i] = 0; + lc1msk_to_irqnr[i] = 0; + lc2msk_to_irqnr[i] = 0; + lc3msk_to_irqnr[i] = 0; + } + } + + ioc_icontrol = &sgi_i3regs->ints; + ioc_timers = &sgi_i3regs->timers; + ioc_tclear = &sgi_i3regs->tclear; + + /* Mask out all interrupts. */ + ioc_icontrol->imask0 = 0; + ioc_icontrol->imask1 = 0; + ioc_icontrol->cmeimask0 = 0; + ioc_icontrol->cmeimask1 = 0; + + /* Now safe to set the exception vector. */ + set_except_vector(0, indyIRQ); + +#ifdef CONFIG_REMOTE_DEBUG + ctype = prom_getcmdline(); + for(i = 0; i < strlen(ctype); i++) { + if(ctype[i]=='k' && ctype[i+1]=='g' && + ctype[i+2]=='d' && ctype[i+3]=='b' && + ctype[i+4]=='=' && ctype[i+5]=='t' && + ctype[i+6]=='t' && ctype[i+7]=='y' && + ctype[i+8]=='d' && + (ctype[i+9] == '1' || ctype[i+9] == '2')) { + printk("KGDB: Using serial line /dev/ttyd%d for " + "session\n", (ctype[i+9] - '0')); + if(ctype[i+9]=='1') + rs_kgdb_hook(1); + else if(ctype[i+9]=='2') + rs_kgdb_hook(0); + else { + printk("KGDB: whoops bogon tty line " + "requested, disabling session\n"); + } + + } + } +#endif +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c --- v2.1.43/linux/arch/mips/sgi/kernel/indy_mc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indy_mc.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,153 @@ +/* $Id: indy_mc.c,v 1.1 1997/06/06 09:36:24 ralf Exp $ + * indy_mc.c: Routines for manipulating the INDY memory controller. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include + +/* #define DEBUG_SGIMC */ + +struct sgimc_misc_ctrl *mcmisc_regs; +unsigned long *rpsscounter; +struct sgimc_dma_ctrl *dmactrlregs; + +static inline char *mconfig_string(unsigned long val) +{ + switch(val & SGIMC_MCONFIG_RMASK) { + case SGIMC_MCONFIG_FOURMB: + return "4MB"; + + case SGIMC_MCONFIG_EIGHTMB: + return "8MB"; + + case SGIMC_MCONFIG_SXTEENMB: + return "16MB"; + + case SGIMC_MCONFIG_TTWOMB: + return "32MB"; + + case SGIMC_MCONFIG_SFOURMB: + return "64MB"; + + case SGIMC_MCONFIG_OTEIGHTMB: + return "128MB"; + + default: + return "wheee, unknown"; + }; +} + +void sgimc_init(void) +{ + unsigned long tmpreg; + + mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); + rpsscounter = (unsigned long *) (KSEG1 + 0x1fa01004); + dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000); + + printk("MC: SGI memory controller Revision %d\n", + (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV); + +#if 0 /* XXX Until I figure out what this bit really indicates XXX */ + /* XXX Is this systemid bit reliable? */ + if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) { + EISA_bus = 1; + printk("with EISA\n"); + } else { + EISA_bus = 0; + printk("no EISA\n"); + } +#endif + +#ifdef DEBUG_SGIMC + prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n", + mconfig_string(mcmisc_regs->mconfig0), + mconfig_string(mcmisc_regs->mconfig1)); + + prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n", + mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1); + prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n", + mcmisc_regs->divider, mcmisc_regs->gioparm); +#endif + + /* Place the MC into a known state. This must be done before + * interrupts are first enabled etc. + */ + + /* Step 1: The CPU/GIO error status registers will not latch + * up a new error status until the register has been + * cleared by the cpu. These status registers are + * cleared by writing any value to them. + */ + mcmisc_regs->cstat = mcmisc_regs->gstat = 0; + + /* Step 2: Enable all parity checking in cpu control register + * zero. + */ + tmpreg = mcmisc_regs->cpuctrl0; + tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | + SGIMC_CCTRL0_R4KNOCHKPARR); + mcmisc_regs->cpuctrl0 = tmpreg; + + /* Step 3: Setup the MC write buffer depth, this is controlled + * in cpu control register 1 in the lower 4 bits. + */ + tmpreg = mcmisc_regs->cpuctrl1; + tmpreg &= ~0xf; + tmpreg |= 0xd; + mcmisc_regs->cpuctrl1 = tmpreg; + + /* Step 4: Initialize the RPSS divider register to run as fast + * as it can correctly operate. The register is laid + * out as follows: + * + * ---------------------------------------- + * | RESERVED | INCREMENT | DIVIDER | + * ---------------------------------------- + * 31 16 15 8 7 0 + * + * DIVIDER determines how often a 'tick' happens, + * INCREMENT determines by how the RPSS increment + * registers value increases at each 'tick'. Thus, + * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101 + */ + mcmisc_regs->divider = 0x101; + + /* Step 5: Initialize GIO64 arbitrator configuration register. + * + * NOTE: If you dork with startup code the HPC init code in + * sgihpc_init() must run before us because of how we + * need to know Guiness vs. FullHouse and the board + * revision on this machine. You have been warned. + */ + + /* First the basic invariants across all gio64 implementations. */ + tmpreg = SGIMC_GIOPARM_HPC64; /* All 1st HPC's interface at 64bits. */ + tmpreg |= SGIMC_GIOPARM_ONEBUS; /* Only one physical GIO bus exists. */ + + if(sgi_guiness) { + /* Guiness specific settings. */ + tmpreg |= SGIMC_GIOPARM_EISA64; /* MC talks to EISA at 64bits */ + tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */ + } else { + /* Fullhouse specific settings. */ + if(sgi_boardid < 2) { + tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */ + tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */ + tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */ + tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */ + } else { + tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */ + tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ + tmpreg |= SGIMC_GIOPARM_PLINEEXP1; + tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ + } + } + mcmisc_regs->gioparm = tmpreg; /* poof */ +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c --- v2.1.43/linux/arch/mips/sgi/kernel/indy_timer.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indy_timer.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,297 @@ +/* $Id: indy_timer.c,v 1.1 1997/06/06 09:36:28 ralf Exp $ + * indy_timer.c: Setting up the clock on the INDY 8254 controller. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The layout of registers for the INDY Dallas 1286 clock chipset. */ +struct indy_clock { + volatile unsigned int hsec; + volatile unsigned int sec; + volatile unsigned int min; + volatile unsigned int malarm; + volatile unsigned int hr; + volatile unsigned int halarm; + volatile unsigned int day; + volatile unsigned int dalarm; + volatile unsigned int date; + volatile unsigned int month; + volatile unsigned int year; + volatile unsigned int cmd; + volatile unsigned int whsec; + volatile unsigned int wsec; + volatile unsigned int _unused0[50]; +}; + +#define INDY_CLOCK_REGS ((struct indy_clock *)(KSEG1ADDR(0x1fbe0000))) + +/* Because of a bug in the i8254 timer we need to use the onchip r4k + * counter as our system wide timer interrupt running at 100HZ. + */ +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_32bit_cp0_register(CP0_COMPARE, newval); +} + +static int set_rtc_mmss(unsigned long nowtime) +{ + struct indy_clock *clock = INDY_CLOCK_REGS; + int retval = 0; + int real_seconds, real_minutes, clock_minutes; + +#define FROB_FROM_CLOCK(x) (((x) & 0xf) | ((((x) & 0xf0) >> 4) * 10)); +#define FROB_TO_CLOCK(x) ((((((x) & 0xff) / 10)<<4) | (((x) & 0xff) % 10)) & 0xff) + + clock->cmd &= ~(0x80); + clock_minutes = clock->min; + clock->cmd |= (0x80); + + clock_minutes = FROB_FROM_CLOCK(clock_minutes); + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + + if(((abs(real_minutes - clock_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + + real_minutes %= 60; + if(abs(real_minutes - clock_minutes) < 30) { + /* Force clock oscillator to be on. */ + clock->month &= ~(0x80); + + /* Write real_seconds and real_minutes into the Dallas. */ + clock->cmd &= ~(0x80); + clock->sec = real_seconds; + clock->min = real_minutes; + clock->cmd |= (0x80); + } else + return -1; + +#undef FROB_FROM_CLOCK +#undef FROB_TO_CLOCK + + return retval; +} + +static long last_rtc_update = 0; + +void indy_timer_interrupt(struct pt_regs *regs) +{ + /* Ack timer and compute new compare. */ + r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + ack_r4ktimer(r4k_cur); + kstat.interrupts[7]++; + do_timer(regs); + + /* We update the Dallas time of day approx. every 11 minutes, + * because of how the numbers work out we need to make + * absolutely sure we do this update within 500ms before the + * next second starts, thus the following code. + */ + 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 */ +} + +static inline unsigned long dosample(volatile unsigned char *tcwp, + volatile unsigned char *tc2p) +{ + unsigned long ct0, ct1; + unsigned char msb, lsb; + + /* Start the counter. */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN); + *tc2p = (SGINT_TCSAMP_COUNTER & 0xff); + *tc2p = (SGINT_TCSAMP_COUNTER >> 8); + + /* Get initial counter invariant */ + ct0 = read_32bit_cp0_register(CP0_COUNT); + + /* Latch and spin until top byte of counter2 is zero */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); + ct1 = read_32bit_cp0_register(CP0_COUNT); + lsb = *tc2p; + msb = *tc2p; + while(msb) { + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); + ct1 = read_32bit_cp0_register(CP0_COUNT); + lsb = *tc2p; + msb = *tc2p; + } + + /* Stop the counter. */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); + + /* Return the difference, this is how far the r4k counter increments + * for every one HZ. + */ + return ct1 - ct0; +} + +/* 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 */ +} + +unsigned long get_indy_time(void) +{ + struct indy_clock *clock = INDY_CLOCK_REGS; + unsigned int year, mon, day, hour, min, sec; + + /* Freeze it. */ + clock->cmd &= ~(0x80); + + /* Read regs. */ + sec = clock->sec; + min = clock->min; + hour = (clock->hr & 0x3f); + day = (clock->date & 0x3f); + mon = (clock->month & 0x1f); + year = clock->year; + + /* Unfreeze clock. */ + clock->cmd |= 0x80; + + /* Frob the bits. */ +#define FROB1(x) (((x) & 0xf) + ((((x) & 0xf0) >> 4) * 10)); +#define FROB2(x) (((x) & 0xf) + (((((x) & 0xf0) >> 4) & 0x3) * 10)); + + /* XXX Should really check that secs register is the same + * XXX as when we first read it and if not go back and + * XXX read the regs above again. + */ + sec = FROB1(sec); min = FROB1(min); day = FROB1(day); + mon = FROB1(mon); year = FROB1(year); + hour = FROB2(hour); + +#undef FROB1 +#undef FROB2 + + /* Wheee... */ + if(year < 45) + year += 30; + if ((year += 1940) < 1970) + year += 100; + + return mktime(year, mon, day, hour, min, sec); +} + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +void indy_timer_init(void) +{ + struct sgi_ioc_timers *p; + volatile unsigned char *tcwp, *tc2p; + + /* Figure out the r4k offset, the algorithm is very simple + * and works in _all_ cases as long as the 8254 counter + * register itself works ok (as an interrupt driving timer + * it does not because of bug, this is why we are using + * the onchip r4k counter/compare register to serve this + * purpose, but for r4k_offset calculation it will work + * ok for us). There are other very complicated ways + * of performing this calculation but this one works just + * fine so I am not going to futz around. ;-) + */ + p = ioc_timers; + tcwp = &p->tcword; + tc2p = &p->tcnt2; + + printk("calculating r4koff... "); + r4k_offset = dosample(tcwp, tc2p); /* First sample. */ + dosample(tcwp, tc2p); /* Eat one... */ + r4k_offset += dosample(tcwp, tc2p); /* Second sample. */ + r4k_offset = (r4k_offset >> 1); /* Get average. */ + r4k_offset = HZ * r4k_offset; /* Multiply by HZ */ + + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + write_32bit_cp0_register(CP0_COMPARE, r4k_cur); + set_cp0_status(ST0_IM, ALLINTS); + sti(); + + /* Read time from the dallas chipset. */ + xtime.tv_sec = get_indy_time(); + xtime.tv_usec = 0; +} + +void indy_8254timer_irq(void) +{ + kstat.interrupts[4]++; + printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); + prom_getchar(); + prom_imode(); +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_flags(flags); cli(); + *tv = xtime; + restore_flags(flags); +} + +void do_settimeofday(struct timeval *tv) +{ + cli(); + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + sti(); +} + diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c --- v2.1.43/linux/arch/mips/sgi/kernel/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/reset.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,25 @@ +/* + * linux/arch/mips/sgi/kernel/process.c + * + * Reset a SGI. + */ +#include +#include +#include + +/* XXX How to pass the reboot command to the firmware??? */ +void sgi_machine_restart(char *command) +{ + for(;;) + prom_imode(); +} + +void sgi_machine_halt(void) +{ + /* XXX */ +} + +void sgi_machine_power_off(void) +{ + /* XXX */ +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.1.43/linux/arch/mips/sgi/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/setup.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,91 @@ +/* $Id: setup.c,v 1.1 1997/06/06 09:36:33 ralf Exp $ + * setup.c: SGI specific setup, including init of the feature struct. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef __GOGOGO__ +#error "... about to fuckup your Indy?" +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern int serial_console; /* in console.c, of course */ + +extern void sgi_machine_restart(char *command); +extern void sgi_machine_halt(void); +extern void sgi_machine_power_off(void); + +struct feature sgi_feature = { +}; + +static void sgi_irq_setup(void) +{ + sgint_init(); +} + +#if 0 +extern void register_console(void (*proc)(const char *)); + +static void sgi_print(const char *p) +{ + char c; + + while((c = *p++) != 0) { + if(c == '\n') + prom_putchar('\r'); + prom_putchar(c); + } +} +#endif + +void sgi_setup(void) +{ + char *ctype; + + irq_setup = sgi_irq_setup; + feature = &sgi_feature; + + _machine_restart = sgi_machine_restart; + _machine_halt = sgi_machine_halt; + _machine_power_off = sgi_machine_power_off; + + /* register_console(sgi_print); */ + + sgi_sysinit(); + + /* Init the INDY HPC I/O controller. Need to call this before + * fucking with the memory controller because it needs to know the + * boardID and whether this is a Guiness or a FullHouse machine. + */ + sgihpc_init(); + + /* Init INDY memory controller. */ + sgimc_init(); + + /* ARCS console environment variable is set to "g?" for + * graphics console, it is set to "d" for the first serial + * line and "d2" for the second serial line. + */ + ctype = prom_getenv("console"); + serial_console = 0; + if(*ctype == 'd') { + if(*(ctype+1)=='2') + serial_console = 1; + else + serial_console = 2; + if(!serial_console) { + prom_printf("Weird console env setting %s\n", ctype); + prom_printf("Press a key to reboot.\n"); + prom_getchar(); + prom_imode(); + } + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c --- v2.1.43/linux/arch/mips/sgi/kernel/system.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/system.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,168 @@ +/* $Id: system.c,v 1.1 1997/06/06 09:36:36 ralf Exp $ + * system.c: Probe the system type using ARCS prom interface library. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include + +#include +#include +#include + +#ifndef __GOGOGO__ +#error "... You're fearless, aren't you?" +#endif + +enum sgi_mach sgimach; + +struct smatch { + char *name; + int type; +}; + +static struct smatch sgi_mtable[] = { + { "SGI-IP4", ip4 }, + { "SGI-IP5", ip5 }, + { "SGI-IP6", ip6 }, + { "SGI-IP7", ip7 }, + { "SGI-IP9", ip9 }, + { "SGI-IP12", ip12 }, + { "SGI-IP15", ip15 }, + { "SGI-IP17", ip17 }, + { "SGI-IP19", ip19 }, + { "SGI-IP20", ip20 }, + { "SGI-IP21", ip21 }, + { "SGI-IP22", ip22 }, + { "SGI-IP25", ip25 }, + { "SGI-IP26", ip26 }, + { "SGI-IP28", ip28 }, + { "SGI-IP30", ip30 }, + { "SGI-IP32", ip32 } +}; + +#define NUM_MACHS 17 /* for now */ + +static struct smatch sgi_cputable[] = { + { "MIPS-R2000", CPU_R2000 }, + { "MIPS-R3000", CPU_R3000 }, + { "MIPS-R3000A", CPU_R3000A }, + { "MIPS-R4000", CPU_R4000SC }, + { "MIPS-R4400", CPU_R4400SC }, + { "MIPS-R4600", CPU_R4600 }, + { "MIPS-R8000", CPU_R8000 }, + { "MIPS-R5000", CPU_R5000 }, + { "MIPS-R5000A", CPU_R5000A } +}; + +#define NUM_CPUS 9 /* for now */ + +static enum sgi_mach string_to_mach(char *s) +{ + int i; + + for(i = 0; i < NUM_MACHS; i++) { + if(!strcmp(s, sgi_mtable[i].name)) + return (enum sgi_mach) sgi_mtable[i].type; + } + prom_printf("\nYeee, could not determine SGI architecture type <%s>\n", s); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + return (enum sgi_mach) 0; +} + +static int string_to_cpu(char *s) +{ + int i; + + for(i = 0; i < NUM_CPUS; i++) { + if(!strcmp(s, sgi_cputable[i].name)) + return sgi_mtable[i].type; + } + prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + return 0; +} + +void sgi_sysinit(void) +{ + pcomponent *p, *toplev, *cpup = 0; + int cputype = -1; + + + /* The root component tells us what machine architecture we + * have here. + */ + p = prom_getchild(PROM_NULL_COMPONENT); + printk("ARCH: %s\n", p->iname); + sgimach = string_to_mach(p->iname); + + /* Now scan for cpu(s). */ + toplev = p = prom_getchild(p); + while(p) { + int ncpus = 0; + + if(p->type == Cpu) { + if(++ncpus > 1) { + prom_printf("\nYeee, SGI MP not ready yet\n"); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + } + printk("CPU: %s ", p->iname); + cpup = p; + cputype = string_to_cpu(cpup->iname); + } + p = prom_getsibling(p); + } + if(cputype == -1) { + prom_printf("\nYeee, could not find cpu ARCS component\n"); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + } + p = prom_getchild(cpup); + while(p) { + switch(p->class) { + case processor: + switch(p->type) { + case Fpu: + printk("FPU<%s> ", p->iname); + break; + + default: + break; + }; + break; + + case cache: + switch(p->type) { + case picache: + printk("ICACHE "); + break; + + case pdcache: + printk("DCACHE "); + break; + + case sccache: + printk("SCACHE "); + break; + + default: + break; + + }; + break; + + default: + break; + }; + p = prom_getsibling(p); + } + printk("\n"); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.1.43/linux/arch/mips/sgi/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/time.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,14 @@ +/* $Id: time.c,v 1.1 1997/06/06 09:36:39 ralf Exp $ + * time.c: Generic SGI time_init() code, this will dispatch to the + * appropriate per-architecture time/counter init code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +extern void indy_timer_init(void); + +void time_init(void) +{ + /* XXX assume INDY for now XXX */ + indy_timer_init(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/Makefile linux/arch/mips/sgi/prom/Makefile --- v2.1.43/linux/arch/mips/sgi/prom/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/Makefile Thu Jun 26 12:33:38 1997 @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 1997/06/06 09:36:49 ralf Exp $ +# Makefile for the SGI arcs prom monitor library routines +# under Linux. +# +# 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... + +OBJS = console.o init.o printf.o memory.o tree.o tags.o env.o \ + cmdline.o misc.o time.o file.o + +all: promlib.a + +promlib.a: $(OBJS) + $(AR) rcs promlib.a $(OBJS) + sync + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/cmdline.c linux/arch/mips/sgi/prom/cmdline.c --- v2.1.43/linux/arch/mips/sgi/prom/cmdline.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/cmdline.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,60 @@ +/* $Id: cmdline.c,v 1.1 1997/06/06 09:36:53 ralf Exp $ + * cmdline.c: Kernel command line creation using ARCS argc/argv. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +extern char arcs_cmdline[CL_SIZE]; + +char *prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +static char *ignored[] = { + "ConsoleIn=", + "ConsoleOut=", + "SystemPartition=", + "OSLoader=", + "OSLoadPartition=", + "OSLoadFilename=" +}; +#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) + +void prom_init_cmdline(void) +{ + char *cp; + int actr, i; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + for(i = 0; i < NENTS(ignored); i++) { + int len = strlen(ignored[i]); + + if(!strncmp(prom_argv[actr], ignored[i], len)) + goto pic_cont; + } + /* Ok, we want it. */ + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + + pic_cont: + actr++; + } + *cp = '\0'; + +#ifdef DEBUG_CMDLINE + prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); +#endif +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/console.c linux/arch/mips/sgi/prom/console.c --- v2.1.43/linux/arch/mips/sgi/prom/console.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/console.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,24 @@ +/* $Id: console.c,v 1.1 1997/06/06 09:36:56 ralf Exp $ + * console.c: SGI arcs console code. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + */ + +#include + +void prom_putchar(char c) +{ + long cnt; + char it = c; + + romvec->write(1, &it, 1, &cnt); +} + +char prom_getchar(void) +{ + long cnt; + char c; + + romvec->read(0, &c, 1, &cnt); + return c; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/env.c linux/arch/mips/sgi/prom/env.c --- v2.1.43/linux/arch/mips/sgi/prom/env.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/env.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,20 @@ +/* $Id: env.c,v 1.1 1997/06/06 09:36:59 ralf Exp $ + * env.c: ARCS environment variable routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include + +#include + +char *prom_getenv(char *name) +{ + return romvec->get_evar(name); +} + +long prom_setenv(char *name, char *value) +{ + return romvec->set_evar(name, value); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/file.c linux/arch/mips/sgi/prom/file.c --- v2.1.43/linux/arch/mips/sgi/prom/file.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/file.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,58 @@ +/* $Id: file.c,v 1.1 1997/06/06 09:37:03 ralf Exp $ + * file.c: ARCS firmware interface to files. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include + +long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, + unsigned long *cnt) +{ + return romvec->get_vdirent(fd, ent, num, cnt); +} + +long prom_open(char *name, enum linux_omode md, unsigned long *fd) +{ + return romvec->open(name, md, fd); +} + +long prom_close(unsigned long fd) +{ + return romvec->close(fd); +} + +long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +{ + return romvec->read(fd, buf, num, cnt); +} + +long prom_getrstatus(unsigned long fd) +{ + return romvec->get_rstatus(fd); +} + +long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +{ + return romvec->write(fd, buf, num, cnt); +} + +long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm) +{ + return romvec->seek(fd, off, sm); +} + +long prom_mount(char *name, enum linux_mountops op) +{ + return romvec->mount(name, op); +} + +long prom_getfinfo(unsigned long fd, struct linux_finfo *buf) +{ + return romvec->get_finfo(fd, buf); +} + +long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk) +{ + return romvec->set_finfo(fd, flags, msk); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/init.c linux/arch/mips/sgi/prom/init.c --- v2.1.43/linux/arch/mips/sgi/prom/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/init.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,59 @@ +/* $Id: init.c,v 1.1 1997/06/06 09:37:06 ralf Exp $ + * init.c: PROM library initialisation code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include + +#include + +/* #define DEBUG_PROM_INIT */ + +/* Master romvec interface. */ +struct linux_romvec *romvec; +struct linux_promblock *sgi_pblock; +int prom_argc; +char **prom_argv, **prom_envp; +unsigned short prom_vers, prom_rev; + +extern void prom_testtree(void); + +int prom_init(int argc, char **argv, char **envp) +{ + struct linux_promblock *pb; + + romvec = ROMVECTOR; + pb = sgi_pblock = PROMBLOCK; + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + if(pb->magic != 0x53435241) { + prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); + while(1) + ; + } + + prom_init_cmdline(); + + prom_vers = pb->ver; + prom_rev = pb->rev; + printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n", + prom_vers, prom_rev); + prom_meminit(); + prom_setup_archtags(); + +#if 0 + prom_testtree(); +#endif + +#ifdef DEBUG_PROM_INIT + { + prom_printf("Press a key to reboot\n"); + (void) prom_getchar(); + romvec->imode(); + } +#endif + return 0; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/memory.c linux/arch/mips/sgi/prom/memory.c --- v2.1.43/linux/arch/mips/sgi/prom/memory.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/memory.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,129 @@ +/* $Id: memory.c,v 1.1 1997/06/06 09:37:10 ralf Exp $ + * memory.c: PROM library functions for acquiring/using memory descriptors + * given to us from the ARCS firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* #define DEBUG */ + +struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr) +{ + return romvec->get_mdesc(curr); +} + +#ifdef DEBUG /* convenient for debugging */ +static char *mtypes[8] = { + "Exception Block", + "ARCS Romvec Page", + "Free/Contig RAM", + "Generic Free RAM", + "Bad Memory", + "Standlong Program Pages", + "ARCS Temp Storage Area", + "ARCS Permanent Storage Area" +}; +#endif + +static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; + +struct prom_pmemblock *prom_getpblock_array(void) +{ + return &prom_pblocks[0]; +} + +static void prom_setup_memupper(void) +{ + struct prom_pmemblock *p, *highest; + + for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { + if(p->base == 0xdeadbeef) + prom_printf("WHEEE, bogus pmemblock\n"); + if(!highest || p->base > highest->base) + highest = p; + } + mips_memory_upper = highest->base + highest->size; +#ifdef DEBUG + prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n", + mips_memory_upper); +#endif +} + +void prom_meminit(void) +{ + struct linux_mdesc *p; + int totram; + int i = 0; + + p = prom_getmdesc(PROM_NULL_MDESC); +#ifdef DEBUG + prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); + while(p) { + prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", + i, p, p->base, p->pages, mtypes[p->type]); + p = prom_getmdesc(p); + i++; + } +#endif + p = prom_getmdesc(PROM_NULL_MDESC); + totram = 0; + i = 0; + while(p) { + if(p->type == free || p->type == fcontig) { + prom_pblocks[i].base = + ((p->base<pages << PAGE_SHIFT; + totram += prom_pblocks[i].size; +#ifdef DEBUG + prom_printf("free_chunk[%d]: base=%08lx size=%d\n", + i, prom_pblocks[i].base, + prom_pblocks[i].size); +#endif + i++; + } + p = prom_getmdesc(p); + } + prom_pblocks[i].base = 0xdeadbeef; + prom_pblocks[i].size = 0; /* indicates last elem. of array */ + printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", + totram, (totram/1024), (totram/1024/1024)); + + /* Setup upper physical memory bound. */ + prom_setup_memupper(); +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +void prom_fixup_mem_map(unsigned long start, unsigned long end) +{ + struct prom_pmemblock *p; + int i, nents; + + /* Determine number of pblockarray entries. */ + p = prom_getpblock_array(); + for(i = 0; p[i].size; i++) + ; + nents = i; + while(start < end) { + for(i = 0; i < nents; i++) { + if((start >= (p[i].base)) && + (start < (p[i].base + p[i].size))) { + start = p[i].base + p[i].size; + start &= PAGE_MASK; + continue; + } + } + set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); + start += PAGE_SIZE; + } +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/misc.c linux/arch/mips/sgi/prom/misc.c --- v2.1.43/linux/arch/mips/sgi/prom/misc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/misc.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,119 @@ +/* + * misc.c: Miscellaneous ARCS PROM routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include + +#include +#include +#include + +extern unsigned long mips_cputype; +extern int initialize_kbd(void); +extern void *sgiwd93_host; +extern void reset_wd33c93(void *instance); + +static inline void shutoff_r4600_cache(void) +{ + unsigned long tmp1, tmp2, tmp3; + + if(mips_cputype != CPU_R4600 && + mips_cputype != CPU_R4640 && + mips_cputype != CPU_R4700) + return; + printk("Disabling R4600 SCACHE\n"); + __asm__ __volatile__(" + .set noreorder + .set mips3 + li %0, 0x1 + dsll %0, 31 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %1, %0 + mfc0 %2, $12 + nop; nop; nop; nop; + li %1, 0x80 + mtc0 %1, $12 + nop; nop; nop; nop; + sh $0, 0(%0) + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %2, $12 + nop; nop; nop; nop; + .set mips2 + .set reorder + " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); +} + +void prom_halt(void) +{ + shutoff_r4600_cache(); + initialize_kbd(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + cli(); + romvec->halt(); +} + +void prom_powerdown(void) +{ + shutoff_r4600_cache(); + initialize_kbd(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + cli(); + romvec->pdown(); +} + +/* XXX is this a soft reset basically? XXX */ +void prom_restart(void) +{ + shutoff_r4600_cache(); + initialize_kbd(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + cli(); + romvec->restart(); +} + +void prom_reboot(void) +{ + shutoff_r4600_cache(); + initialize_kbd(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + cli(); + romvec->reboot(); +} + +void prom_imode(void) +{ + shutoff_r4600_cache(); + initialize_kbd(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + cli(); + romvec->imode(); +} + +long prom_cfgsave(void) +{ + return romvec->cfg_save(); +} + +struct linux_sysid *prom_getsysid(void) +{ + return romvec->get_sysid(); +} + +void prom_cacheflush(void) +{ + romvec->cache_flush(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/printf.c linux/arch/mips/sgi/prom/printf.c --- v2.1.43/linux/arch/mips/sgi/prom/printf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/printf.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,34 @@ +/* $Id: printf.c,v 1.1 1997/06/06 09:37:17 ralf Exp $ + * printf.c: Putting things on the screen using SGI arcs + * PROM facilities. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + */ + +#include + +#include + +static char ppbuf[1024]; + +void +prom_printf(char *fmt, ...) +{ + va_list args; + char ch, *bptr; + int i; + + va_start(args, fmt); + i = vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while((ch = *(bptr++)) != 0) { + if(ch == '\n') + prom_putchar('\r'); + + prom_putchar(ch); + } + va_end(args); + return; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/salone.c linux/arch/mips/sgi/prom/salone.c --- v2.1.43/linux/arch/mips/sgi/prom/salone.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/salone.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,24 @@ +/* $Id: salone.c,v 1.1 1997/06/06 09:37:20 ralf Exp $ + * salone.c: Routines to load into memory and execute stand-along + * program images using ARCS PROM firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include + +long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr) +{ + return romvec->load(name, end, pc, eaddr); +} + +long prom_invoke(unsigned long pc, unsigned long sp, long argc, + char **argv, char **envp) +{ + return romvec->invoke(pc, sp, argc, argv, envp); +} + +long prom_exec(char *name, long argc, char **argv, char **envp) +{ + return romvec->exec(name, argc, argv, envp); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/tags.c linux/arch/mips/sgi/prom/tags.c --- v2.1.43/linux/arch/mips/sgi/prom/tags.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/tags.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,67 @@ +/* $Id: tags.c,v 1.1 1997/06/06 09:37:22 ralf Exp $ + * tags.c: Initialize the arch tags the way the MIPS kernel setup + * expects. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include + +#include +#include +#include +#include + +/* XXX This tag thing is a fucking rats nest, I'm very inclined to completely + * XXX rework the MIPS people's multi-arch code _NOW_. + */ + +static unsigned long machtype_SGI_INDY = MACH_SGI_INDY; +static unsigned long machgroup_SGI = MACH_GROUP_SGI; +static unsigned long memlower_SGI_INDY = (KSEG0 + SGIMC_SEG0_BADDR); +static unsigned long cputype_SGI_INDY = CPU_R4400SC; +static unsigned long tlb_entries_SGI_INDY = 48; +static unsigned long dummy_SGI_INDY = 0; +static struct drive_info_struct dummy_dinfo_SGI_INDY = { { 0, }, }; +char arcs_cmdline[CL_SIZE]; + +#define TAG(t,l) {tag_##t,(l)} /* XXX RATS NEST CODE!!! XXX */ +#define TAGVAL(v) (void*)&(v) /* XXX FUCKING LOSING!!! XXX */ + +tag_def taglist_sgi_indy[] = { + {TAG(machtype, ULONGSIZE), TAGVAL(machtype_SGI_INDY)}, + {TAG(machgroup, ULONGSIZE), TAGVAL(machgroup_SGI)}, + {TAG(memlower, ULONGSIZE), TAGVAL(memlower_SGI_INDY)}, + {TAG(cputype, ULONGSIZE), TAGVAL(cputype_SGI_INDY)}, + {TAG(tlb_entries, ULONGSIZE), TAGVAL(tlb_entries_SGI_INDY)}, + {TAG(vram_base, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, + {TAG(drive_info, DRVINFOSIZE), TAGVAL(dummy_dinfo_SGI_INDY)}, + {TAG(mount_root_rdonly, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, + {TAG(command_line, CL_SIZE), TAGVAL(arcs_cmdline[0])}, + {TAG(dummy, 0), NULL} + /* XXX COLOSTOMY BAG!!!! XXX */ +}; + +void prom_setup_archtags(void) +{ + tag_def *tdp = &taglist_sgi_indy[0]; + tag *tp; + + tp = (tag *) (mips_memory_upper - sizeof(tag)); + while(tdp->t.tag != tag_dummy) { + unsigned long size; + char *d; + + *tp = tdp->t; + size = tp->size; + d = (char *) tdp->d; + tp = (tag *)(((unsigned long)tp) - (tp->size)); + if(size) + memcpy(tp, d, size); + + tp--; + tdp++; + } + *tp = tdp->t; /* copy last dummy element over */ +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/time.c linux/arch/mips/sgi/prom/time.c --- v2.1.43/linux/arch/mips/sgi/prom/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/time.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,17 @@ +/* $Id: time.c,v 1.1 1997/06/06 09:37:26 ralf Exp $ + * time.c: Extracting time information from ARCS prom. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include + +struct linux_tinfo *prom_gettinfo(void) +{ + return romvec->get_tinfo(); +} + +unsigned long prom_getrtime(void) +{ + return romvec->get_rtime(); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sgi/prom/tree.c linux/arch/mips/sgi/prom/tree.c --- v2.1.43/linux/arch/mips/sgi/prom/tree.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/prom/tree.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,107 @@ +/* $Id: tree.c,v 1.1 1997/06/06 09:37:29 ralf Exp $ + * tree.c: PROM component device tree code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include + +#define DEBUG_PROM_TREE + +pcomponent *prom_getsibling(pcomponent *this) +{ + if(this == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->next_component(this); +} + +pcomponent *prom_getchild(pcomponent *this) +{ + return romvec->child_component(this); +} + +pcomponent *prom_getparent(pcomponent *child) +{ + if(child == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->parent_component(child); +} + +long prom_getcdata(void *buffer, pcomponent *this) +{ + return romvec->component_data(buffer, this); +} + +pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data) +{ + return romvec->child_add(this, tmp, data); +} + +long prom_delcomponent(pcomponent *this) +{ + return romvec->comp_del(this); +} + +pcomponent *prom_componentbypath(char *path) +{ + return romvec->component_by_path(path); +} + +#ifdef DEBUG_PROM_TREE +static char *classes[] = { + "system", "processor", "cache", "adapter", "controller", "peripheral", + "memory" +}; + +static char *types[] = { + "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", + "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", + "multi-func adapter", "disk controller", "tp controller", + "cdrom controller", "worm controller", "serial controller", + "net controller", "display controller", "parallel controller", + "pointer controller", "keyboard controller", "audio controller", + "misc controller", "disk peripheral", "floppy peripheral", + "tp peripheral", "modem peripheral", "monitor peripheral", + "printer peripheral", "pointer peripheral", "keyboard peripheral", + "terminal peripheral", "line peripheral", "net peripheral", + "misc peripheral", "anonymous" +}; + +static char *iflags[] = { + "bogus", "read only", "removable", "console in", "console out", + "input", "output" +}; + +static void dump_component(pcomponent *p) +{ + prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", + p, classes[p->class], types[p->type], + iflags[p->iflags], p->vers, p->rev); + prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", + p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); +} + +static void traverse(pcomponent *p, int op) +{ + dump_component(p); + if(prom_getchild(p)) + traverse(prom_getchild(p), 1); + if(prom_getsibling(p) && op) + traverse(prom_getsibling(p), 1); +} + +void prom_testtree(void) +{ + pcomponent *p; + + p = prom_getchild(PROM_NULL_COMPONENT); + dump_component(p); + p = prom_getchild(p); + while(p) { + dump_component(p); + p = prom_getsibling(p); + } + prom_printf("press a key\n"); + prom_getchar(); +} +#endif diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile --- v2.1.43/linux/arch/mips/sni/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/Makefile Thu Jun 26 12:33:38 1997 @@ -0,0 +1,22 @@ +# +# Makefile for the SNI specific part of the 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: sni.o +O_TARGET := sni.o +O_OBJS := hw-access.o int-handler.o io.o pci.o reset.o setup.o + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c --- v2.1.43/linux/arch/mips/sni/hw-access.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/hw-access.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,159 @@ +/* + * Low-level hardware access stuff for SNI RM200 PCI + * + * 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) 1996 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int FLOPPY_IRQ; +extern int FLOPPY_DMA; + +/* + * How to access the FDC's registers. + */ +static unsigned char +fd_inb(unsigned int port) +{ + return inb_p(port); +} + +static void +fd_outb(unsigned char value, unsigned int port) +{ + outb_p(value, port); +} + +/* + * How to access the floppy DMA functions. + */ +static void +fd_enable_dma(void) +{ + enable_dma(FLOPPY_DMA); +} + +static void +fd_disable_dma(void) +{ + disable_dma(FLOPPY_DMA); +} + +static int +fd_request_dma(void) +{ + return request_dma(FLOPPY_DMA, "floppy"); +} + +static void +fd_free_dma(void) +{ + free_dma(FLOPPY_DMA); +} + +static void +fd_clear_dma_ff(void) +{ + clear_dma_ff(FLOPPY_DMA); +} + +static void +fd_set_dma_mode(char mode) +{ + set_dma_mode(FLOPPY_DMA, mode); +} + +static void +fd_set_dma_addr(unsigned int addr) +{ + set_dma_addr(FLOPPY_DMA, addr); +} + +static void +fd_set_dma_count(unsigned int count) +{ + set_dma_count(FLOPPY_DMA, count); +} + +static int +fd_get_dma_residue(void) +{ + return get_dma_residue(FLOPPY_DMA); +} + +static void +fd_enable_irq(void) +{ + enable_irq(FLOPPY_IRQ); +} + +static void +fd_disable_irq(void) +{ + disable_irq(FLOPPY_IRQ); +} + +void +sni_fd_cacheflush(const void *addr, size_t size) +{ + flush_cache_all(); +} + +/* + * RTC stuff (This is a guess on how the RM handles this ...) + */ +static unsigned char +rtc_read_data(unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + return inb_p(RTC_PORT(1)); +} + +static void +rtc_write_data(unsigned char data, unsigned long addr) +{ + outb_p(addr, RTC_PORT(0)); + outb_p(data, RTC_PORT(1)); +} + +struct feature sni_rm200_pci_feature = { + /* + * How to access the floppy controller's ports + */ + fd_inb, + fd_outb, + /* + * How to access the floppy DMA functions. + */ + fd_enable_dma, + fd_disable_dma, + fd_request_dma, + fd_free_dma, + fd_clear_dma_ff, + fd_set_dma_mode, + fd_set_dma_addr, + fd_set_dma_count, + fd_get_dma_residue, + fd_enable_irq, + fd_disable_irq, + /* + * How to access the RTC functions. + */ + rtc_read_data, + rtc_write_data +}; diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S --- v2.1.43/linux/arch/mips/sni/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/int-handler.S Thu Jun 26 12:33:38 1997 @@ -0,0 +1,174 @@ +/* + * SNI RM200 PCI specific interrupt handler code. + * + * Copyright (C) 1994 - 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + + .set noreorder + .set noat + .align 5 + NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp) + SAVE_ALL + REG_S sp,PT_OR2(sp) + CLI + /* + * Asume we received an interrupt from the PCI ASIC. + */ + .set at + lui s0,%hi(SNI_PORT_BASE) + li a0,0x0f + sb a0,%lo(SNI_PORT_BASE+0x20)(s0) # poll command + lb a0,%lo(SNI_PORT_BASE+0x20)(s0) # read result + bgtz a0,poll_second + andi a0,7 + beq a0,2,poll_second # cascade? + li s1,1 # delay slot + /* + * Acknowledge first pic + */ + lb t2,%lo(SNI_PORT_BASE+0x21)(s0) + lui s4,%hi(cache_21) + lb t0,%lo(cache_21)(s4) + sllv s1,s1,a0 + or t0,s1 + sb t0,%lo(cache_21)(s4) + sb t0,%lo(SNI_PORT_BASE+0x21)(s0) + li t2,0x20 + sb t2,%lo(SNI_PORT_BASE+0x20)(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + /* + * Unblock first pic + */ + lbu t1,%lo(SNI_PORT_BASE+0x21)(s0) + lb t1,%lo(cache_21)(s4) + nor s1,zero,s1 + and t1,s1 + sb t1,%lo(cache_21)(s4) + jr v0 + sb t1,%lo(SNI_PORT_BASE+0x21)(s0) # delay slot + + /* + * Cascade interrupt from second PIC + */ + .align 5 +poll_second: li a0,0x0f + sb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # poll command + lb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # read result + bgtz a0,3f + andi a0,7 + /* + * Acknowledge second pic + */ + lbu t2,%lo(SNI_PORT_BASE+0xa1)(s0) + lui s4,%hi(cache_A1) + lb t3,%lo(cache_A1)(s4) + sllv s1,s1,a0 + or t3,s1 + sb t3,%lo(cache_A1)(s4) + sb t3,%lo(SNI_PORT_BASE+0xa1)(s0) + li t3,0x20 + sb t3,%lo(SNI_PORT_BASE+0xa0)(s0) + sb t3,%lo(SNI_PORT_BASE+0x20)(s0) + /* + * Now call the real handler + */ + la t3,IRQ_vectors + addiu a0,8 + sll t2,a0,PTRLOG + addu t3,t2 + LONG_L t3,(t3) + jalr t3 + nop # delay slot + /* + * Unblock second pic + */ + lb t1,%lo(SNI_PORT_BASE+0xa1)(s0) + lb t1,%lo(cache_A1)(s4) + subu t0,1 + nor s1,zero,s1 + and t1,t1,s1 + sb t1,%lo(cache_A1)(s4) + jr v0 + sb t1,%lo(SNI_PORT_BASE+0xa1)(s0) # delay slot + +/* + * FIXME: This is definatly wrong but I'll have to do it this way + * 'till I get more hardware info. + * XXX: Apparently the Lance is attached to interrupt #5. + */ +#ifdef CONFIG_PCNET32 + +/* + * FIXME: detect this address + */ +#define LANCE_BASE 0xbb000100 + +/* Offsets from base I/O address. */ +#define LANCE_DATA 0x10 +#define LANCE_ADDR 0x12 +#define LANCE_RESET 0x14 +#define LANCE_BUS_IF 0x16 +#define LANCE_TOTAL_SIZE 0x18 + +/* + * ... check if we were interrupted by the Lance ... + */ +3: lh s0,LANCE_BASE+LANCE_ADDR + sh zero,LANCE_BASE+LANCE_ADDR + lh t1,LANCE_BASE+LANCE_DATA + andi t2,t1,0x80 + beqz t1,3f # no Lance interrupt? + mfc0 t0,CP0_STATUS # delay slot + ori t0,0x041f + xori t0,0x041e + mtc0 t0,CP0_STATUS + li a0,PCIMT_IRQ_ETHERNET + jal do_IRQ + move a1,sp # delay slot + sh s0,LANCE_BASE+LANCE_ADDR + mfc0 t0,CP0_STATUS + ori t0,0x0401 + xori t0,0x0001 + mtc0 t0,CP0_STATUS + j ret_from_sys_call + nop # delay slot + +#endif /* CONFIG_PCNET32 */ + +#ifdef CONFIG_SCSI_NCR53C8XX + +/* + * ... check if we were interrupted by the NCR ... + */ +3: lb t0,PCIMT_CSITPEND + andi t0,0x40 + bnez t0,3f # bit 6 == 0 -> SCSI IRQ + nop # delay slot + jal do_fast_IRQ + li a0,PCIMT_IRQ_SCSI # delay slot + j return + nop # delay slot + +#endif /* CONFIG_SCSI_NCR53C8XX */ + +/* + * "Jump extender" to reach spurious_interrupt + */ +3: j spurious_interrupt + nop # delay slot + END(sni_rm200_pci_handle_int) diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c --- v2.1.43/linux/arch/mips/sni/io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/io.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,172 @@ +/* + * 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. + * + * Low level I/O functions for SNI. + */ +#include +#include +#include +#include +#include +#include + +unsigned char sni_map_isa_cache; + +#define unused __attribute__((unused)) + +/* + * The PCIMT_CSMAPISA is shared by all processors; we need locking. + * + * XXX It's legal to use all the I/O memory access functions in interrupt + * code, so we need to use the _irq locking stuff which may result in + * significant IRQ latencies. + */ +static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED; + +/* + * Urgs... We only can see a 16mb window of the 4gb EISA address space + * at PCIMT_EISA_BASE. Maladia segmentitis ... + * + * XXX Check out if accessing PCIMT_CSMAPISA really is slow. + * For now assume so. + */ +static inline void update_isa_cache(unsigned long address) +{ + unsigned char upper; + + upper = address >> 24; + if (sni_map_isa_cache != upper) { + sni_map_isa_cache = upper; + *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; + } +} + +static unsigned char sni_readb(unsigned long addr) +{ + unsigned char res; + + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); + spin_unlock_irq(&csmapisa_lock); + + return res; +} + +static unsigned short sni_readw(unsigned long addr) +{ + unsigned short res; + + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); + spin_unlock_irq(&csmapisa_lock); + + return res; +} + +static unsigned int sni_readl(unsigned long addr) +{ + unsigned int res; + + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); + spin_unlock_irq(&csmapisa_lock); + + return res; +} + +static void sni_writeb(unsigned char val, unsigned long addr) +{ + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; + spin_unlock_irq(&csmapisa_lock); +} + +static void sni_writew(unsigned short val, unsigned long addr) +{ + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; + spin_unlock_irq(&csmapisa_lock); +} + +static void sni_writel(unsigned int val, unsigned long addr) +{ + spin_lock_irq(&csmapisa_lock); + update_isa_cache(addr); + addr &= 0xffffff; + *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; + spin_unlock_irq(&csmapisa_lock); +} + +static void sni_memset_io(unsigned long addr, int val, unsigned long len) +{ + unsigned long waddr; + + waddr = PCIMT_EISA_BASE | (addr & 0xffffff); + spin_lock_irq(&csmapisa_lock); + while(len) { + unsigned long fraglen; + + fraglen = (~addr + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + update_isa_cache(addr); + memset((char *)waddr, val, fraglen); + addr += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } + spin_unlock_irq(&csmapisa_lock); +} + +static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) +{ + unsigned long waddr; + + waddr = PCIMT_EISA_BASE | (from & 0xffffff); + spin_lock_irq(&csmapisa_lock); + while(len) { + unsigned long fraglen; + + fraglen = (~from + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + update_isa_cache(from); + memcpy((void *)to, (void *)waddr, fraglen); + to += fraglen; + from += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } + spin_unlock_irq(&csmapisa_lock); +} + +static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) +{ + unsigned long waddr; + + waddr = PCIMT_EISA_BASE | (to & 0xffffff); + spin_lock_irq(&csmapisa_lock); + while(len) { + unsigned long fraglen; + + fraglen = (~to + 1) & 0xffffff; + fraglen = (fraglen < len) ? fraglen : len; + update_isa_cache(to); + memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen); + to += fraglen; + from += fraglen; + waddr = waddr + fraglen - 0x1000000; + len -= fraglen; + } + spin_unlock_irq(&csmapisa_lock); +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.1.43/linux/arch/mips/sni/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/pci.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,135 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PCI + +extern inline u32 mkaddr(unsigned char bus, unsigned char dev_fn, + unsigned char where) +{ + return ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | + (where & 0xfc); +} + +static unsigned long sni_rm200_pcibios_fixup (unsigned long memory_start, + unsigned long memory_end) +{ + /* + * TODO: Fix PCI_INTERRUPT_LINE register for onboard cards. + * Take care of RM300 revision D boards for where the network + * slot became an ordinary PCI slot. + */ + return memory_start; +} + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int sni_rm200_pcibios_read_config_byte (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char *val) +{ + u32 res; + + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff; + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_read_config_word (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short *val) +{ + u32 res; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff; + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_read_config_dword (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int *val) +{ + u32 res; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = le32_to_cpu(res); + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_byte (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char val) +{ + /* To do */ + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_word (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short val) +{ + /* To do */ + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_dword (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + *(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val); + + return PCIBIOS_SUCCESSFUL; +} + +__initfunc(unsigned long sni_rm200_pcibios_init(unsigned long memory_start, unsigned long memory_end)) +{ + _pcibios_fixup = sni_rm200_pcibios_fixup; + _pcibios_read_config_byte = sni_rm200_pcibios_read_config_byte; + _pcibios_read_config_word = sni_rm200_pcibios_read_config_word; + _pcibios_read_config_dword = sni_rm200_pcibios_read_config_dword; + _pcibios_write_config_byte = sni_rm200_pcibios_write_config_byte; + _pcibios_write_config_word = sni_rm200_pcibios_write_config_word; + _pcibios_write_config_dword = sni_rm200_pcibios_write_config_dword; + + return memory_start; +} + +#endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/reset.c linux/arch/mips/sni/reset.c --- v2.1.43/linux/arch/mips/sni/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/reset.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,51 @@ +/* + * linux/arch/mips/sni/process.c + * + * Reset a SNI machine. + */ +#include +#include +#include +#include + +/* + * 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. + */ +static inline void +kb_wait(void) +{ + int i; + + for (i=0; i<0x10000; i++) + if ((inb_p(0x64) & 0x02) == 0) + break; +} + +/* XXX This ends up at the ARC firmware prompt ... */ +void sni_machine_restart(char *command) +{ + int i, j; + + /* This does a normal via the keyboard controller like a PC. + We can do that easier ... */ + sti(); + for (;;) { + for (i=0; i<100; i++) { + kb_wait(); + for(j = 0; j < 100000 ; j++) + /* nothing */; + outb_p(0xfe,0x64); /* pulse reset low */ + } + } +} + +void sni_machine_halt(void) +{ +} + +void sni_machine_power_off(void) +{ + *(volatile unsigned char *)PCIMT_CSWCSM = 0xfd; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.1.43/linux/arch/mips/sni/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/setup.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,158 @@ +/* + * Setup pointers to hardware dependand routines. + * + * 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) 1996, 1997 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Initial irq handlers. + */ +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; + +extern asmlinkage void sni_rm200_pci_handle_int(void); +extern asmlinkage void sni_fd_cacheflush(const void *addr, size_t size); +extern struct feature sni_rm200_pci_feature; + +extern void sni_machine_restart(char *command); +extern void sni_machine_halt(void); +extern void sni_machine_power_off(void); + +__initfunc(static void sni_irq_setup(void)) +{ + set_except_vector(0, sni_rm200_pci_handle_int); + request_region(0x20,0x20, "pic1"); + request_region(0xa0,0x20, "pic2"); + setup_x86_irq(2, &irq2); + /* + * IRQ0 seems to be the irq for PC style stuff. + * I don't know how to handle the debug button interrupt, so + * don't use this button yet or bad things happen ... + */ + set_cp0_status(ST0_IM, IE_IRQ0); +} + +void (*board_time_init)(struct irqaction *irq); + +__initfunc(static void sni_rm200_pci_time_init(struct irqaction *irq)) +{ + /* 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 */ + setup_x86_irq(0, irq); +} + +unsigned char aux_device_present; +extern unsigned long sni_rm200_pcibios_init (unsigned long memory_start, + unsigned long memory_end); +extern unsigned char sni_map_isa_cache; + +/* + * A bit more gossip about the iron we're running on ... + */ +static inline void sni_pcimt_detect(void) +{ + char boardtype[80]; + unsigned char csmsr; + char *p = boardtype; + int asic; + + csmsr = *(volatile unsigned char *)PCIMT_CSMSR; + + p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300"); + if ((csmsr & 0x80) == 0) + p += sprintf(p, ", board revision %s", + (csmsr & 0x20) ? "D" : "C"); + asic = csmsr & 0x80; + asic = (csmsr & 0x08) ? asic : !asic; + p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1"); + printk("%s.\n", boardtype); +} + +__initfunc(void sni_rm200_pci_setup(void)) +{ + tag *atag; + + /* + * We just check if a tag_screen_info can be gathered + * in setup_arch(), if yes we don't proceed futher... + */ + atag = bi_TagFind(tag_screen_info); + if (!atag) { + /* + * If no, we try to find the tag_arc_displayinfo which is + * always created by Milo for an ARC box (for now Milo only + * works on ARC boxes :) -Stoned. + */ + atag = bi_TagFind(tag_arcdisplayinfo); + if (atag) { + screen_info.orig_x = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x; + screen_info.orig_y = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y; + screen_info.orig_video_cols = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns; + screen_info.orig_video_lines = + ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; + } + } + + sni_pcimt_detect(); + + irq_setup = sni_irq_setup; + fd_cacheflush = sni_fd_cacheflush; // Will go away + feature = &sni_rm200_pci_feature; + port_base = SNI_PORT_BASE; + + /* + * Setup (E)ISA I/O memory access stuff + */ + isa_slot_offset = 0xb0000000; + // sni_map_isa_cache = 0; + EISA_bus = 1; + + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + /* XXX FIXME: CONFIG_RTC */ + request_region(0x70,0x10,"rtc"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); + board_time_init = sni_rm200_pci_time_init; + + _machine_restart = sni_machine_restart; + _machine_halt = sni_machine_halt; + _machine_power_off = sni_machine_power_off; + + aux_device_present = 0xaa; + + /* + * Some cluefull person has placed the PCI config data directly in + * the I/O port space ... + */ + request_region(0xcfc,0x04,"PCI config data"); + _pcibios_init = sni_rm200_pcibios_init; +} diff -u --recursive --new-file v2.1.43/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile --- v2.1.43/linux/arch/mips/tools/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/tools/Makefile Thu Jun 26 12:33:38 1997 @@ -0,0 +1,26 @@ +# Makefile for MIPS kernel build tools. +# +# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) +# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) +# +TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: $(TARGET) + +$(TARGET): offset.h + cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) + +offset.h: offset.s + sed -n '/^@@@/s///p' $^ >$@ + +offset.s: offset.c + +clean: + rm -f offset.s $(TARGET).new + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.43/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c --- v2.1.43/linux/arch/mips/tools/offset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/tools/offset.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,127 @@ +/* + * offset.c: Calculate pt_regs and task_struct offsets. + * + * Copyright (C) 1996 David S. Miller + * Made portable by Ralf Baechle + */ + +#include +#include + +#include +#include + +#define text(t) __asm__("\n@@@" t) +#define _offset(type, member) (&(((type *)NULL)->member)) + +#define offset(string, ptr, member) \ + __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) +#define size(string, size) \ + __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) +#define linefeed text("") + +text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */"); +text(""); +text("#ifndef _MIPS_OFFSET_H"); +text("#define _MIPS_OFFSET_H"); +text(""); + +void output_ptreg_defines(void) +{ + text("/* MIPS pt_regs offsets. */"); + offset("#define PT_R0 ", struct pt_regs, regs[0]); + offset("#define PT_R1 ", struct pt_regs, regs[1]); + offset("#define PT_R2 ", struct pt_regs, regs[2]); + offset("#define PT_R3 ", struct pt_regs, regs[3]); + offset("#define PT_R4 ", struct pt_regs, regs[4]); + offset("#define PT_R5 ", struct pt_regs, regs[5]); + offset("#define PT_R6 ", struct pt_regs, regs[6]); + offset("#define PT_R7 ", struct pt_regs, regs[7]); + offset("#define PT_R8 ", struct pt_regs, regs[8]); + offset("#define PT_R9 ", struct pt_regs, regs[9]); + offset("#define PT_R10 ", struct pt_regs, regs[10]); + offset("#define PT_R11 ", struct pt_regs, regs[11]); + offset("#define PT_R12 ", struct pt_regs, regs[12]); + offset("#define PT_R13 ", struct pt_regs, regs[13]); + offset("#define PT_R14 ", struct pt_regs, regs[14]); + offset("#define PT_R15 ", struct pt_regs, regs[15]); + offset("#define PT_R16 ", struct pt_regs, regs[16]); + offset("#define PT_R17 ", struct pt_regs, regs[17]); + offset("#define PT_R18 ", struct pt_regs, regs[18]); + offset("#define PT_R19 ", struct pt_regs, regs[19]); + offset("#define PT_R20 ", struct pt_regs, regs[20]); + offset("#define PT_R21 ", struct pt_regs, regs[21]); + offset("#define PT_R22 ", struct pt_regs, regs[22]); + offset("#define PT_R23 ", struct pt_regs, regs[23]); + offset("#define PT_R24 ", struct pt_regs, regs[24]); + offset("#define PT_R25 ", struct pt_regs, regs[25]); + offset("#define PT_R26 ", struct pt_regs, regs[26]); + offset("#define PT_R27 ", struct pt_regs, regs[27]); + offset("#define PT_R28 ", struct pt_regs, regs[28]); + offset("#define PT_R29 ", struct pt_regs, regs[29]); + offset("#define PT_R30 ", struct pt_regs, regs[30]); + offset("#define PT_R31 ", struct pt_regs, regs[31]); + offset("#define PT_LO ", struct pt_regs, lo); + offset("#define PT_HI ", struct pt_regs, hi); + offset("#define PT_OR2 ", struct pt_regs, orig_reg2); + offset("#define PT_OR7 ", struct pt_regs, orig_reg7); + offset("#define PT_EPC ", struct pt_regs, cp0_epc); + offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); + offset("#define PT_STATUS ", struct pt_regs, cp0_status); + offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); + size("#define PT_SIZE ", struct pt_regs); + linefeed; +} + +void output_task_defines(void) +{ + text("/* MIPS task_struct offsets. */"); + offset("#define TASK_STATE ", struct task_struct, state); + offset("#define TASK_COUNTER ", struct task_struct, counter); + offset("#define TASK_PRIORITY ", struct task_struct, priority); + offset("#define TASK_SIGNAL ", struct task_struct, signal); + offset("#define TASK_BLOCKED ", struct task_struct, blocked); + offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_MM ", struct task_struct, mm); + linefeed; +} + +void output_thread_defines(void) +{ + text("/* MIPS specific thread_struct offsets. */"); + offset("#define THREAD_REG16 ", struct task_struct, tss.reg16); + offset("#define THREAD_REG17 ", struct task_struct, tss.reg17); + offset("#define THREAD_REG18 ", struct task_struct, tss.reg18); + offset("#define THREAD_REG19 ", struct task_struct, tss.reg19); + offset("#define THREAD_REG20 ", struct task_struct, tss.reg20); + offset("#define THREAD_REG21 ", struct task_struct, tss.reg21); + offset("#define THREAD_REG22 ", struct task_struct, tss.reg22); + offset("#define THREAD_REG23 ", struct task_struct, tss.reg23); + offset("#define THREAD_REG28 ", struct task_struct, tss.reg28); + offset("#define THREAD_REG29 ", struct task_struct, tss.reg29); + offset("#define THREAD_REG30 ", struct task_struct, tss.reg30); + offset("#define THREAD_REG31 ", struct task_struct, tss.reg31); + offset("#define THREAD_STATUS ", struct task_struct, tss.cp0_status); + offset("#define THREAD_FPU ", struct task_struct, tss.fpu); + offset("#define THREAD_BVADDR ", struct task_struct, tss.cp0_badvaddr); + offset("#define THREAD_ECODE ", struct task_struct, tss.error_code); + offset("#define THREAD_TRAPNO ", struct task_struct, tss.trap_no); + offset("#define THREAD_KSP ", struct task_struct, tss.ksp); + offset("#define THREAD_PGDIR ", struct task_struct, tss.pg_dir); + offset("#define THREAD_MFLAGS ", struct task_struct, tss.mflags); + offset("#define THREAD_CURDS ", struct task_struct, tss.current_ds); + offset("#define THREAD_TRAMP ", struct task_struct, tss.irix_trampoline); + offset("#define THREAD_OLDCTX ", struct task_struct, tss.irix_oldctx); + linefeed; +} + +void output_mm_defines(void) +{ + text("/* Linux mm_struct offsets. */"); + offset("#define MM_COUNT ", struct mm_struct, count); + offset("#define MM_PGD ", struct mm_struct, pgd); + offset("#define MM_CONTEXT ", struct mm_struct, context); + linefeed; +} + +text("#endif /* !(_MIPS_OFFSET_H) */"); diff -u --recursive --new-file v2.1.43/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.1.43/linux/arch/sparc/config.in Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc/config.in Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.35 1997/04/07 06:54:09 davem Exp $ +# $Id: config.in,v 1.36 1997/06/17 03:54:47 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # diff -u --recursive --new-file v2.1.43/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.1.43/linux/arch/sparc/defconfig Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc/defconfig Thu Jun 26 12:33:38 1997 @@ -64,6 +64,7 @@ CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y CONFIG_BINFMT_JAVA=m # @@ -103,6 +104,7 @@ # CONFIG_IP_MROUTE is not set CONFIG_IP_ALIAS=m # CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.43/linux/arch/sparc64/config.in Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/config.in Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.6 1997/04/17 20:35:42 jj Exp $ +# $Id: config.in,v 1.7 1997/06/17 03:54:52 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.43/linux/arch/sparc64/defconfig Thu May 15 16:48:02 1997 +++ linux/arch/sparc64/defconfig Thu Jun 26 12:33:38 1997 @@ -46,7 +46,7 @@ # Misc Linux/SPARC drivers # # CONFIG_SUN_OPENPROMIO is not set -# CONFIG_SUN_MOSTEK_RTC is not set +CONFIG_SUN_MOSTEK_RTC=y # CONFIG_SUN_OPENPROMFS is not set CONFIG_NET=y CONFIG_SYSVIPC=y @@ -61,7 +61,8 @@ # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_LOOP is not set # @@ -75,6 +76,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) @@ -88,8 +90,10 @@ # # # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPX=y +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=y +# CONFIG_IPDDP is not set # CONFIG_AX25 is not set # @@ -134,6 +138,9 @@ # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_DCACHE_PRELOAD is not set +# CONFIG_OMIRR is not set +# CONFIG_TRANS_NAMES is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y # CONFIG_FAT_FS is not set @@ -149,6 +156,7 @@ CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.1.43/linux/arch/sparc64/kernel/Makefile Thu May 29 21:53:04 1997 +++ linux/arch/sparc64/kernel/Makefile Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.22 1997/05/27 19:30:17 jj Exp $ +# $Id: Makefile,v 1.23 1997/06/06 10:56:20 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -18,7 +18,8 @@ O_TARGET := kernel.o O_OBJS := etrap.o rtrap.o hack.o process.o setup.o cpu.o idprom.o \ systbls.o traps.o entry.o devices.o auxio.o ioport.o \ - irq.o ptrace.o time.o sys_sparc.o signal.o winfixup.o + irq.o ptrace.o time.o sys_sparc.o signal.o winfixup.o \ + unaligned.o OX_OBJS := sparc64_ksyms.o ifdef CONFIG_SPARC32_COMPAT diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c --- v2.1.43/linux/arch/sparc64/kernel/binfmt_elf32.c Sat May 24 09:10:23 1997 +++ linux/arch/sparc64/kernel/binfmt_elf32.c Thu Jun 26 12:33:38 1997 @@ -6,6 +6,8 @@ #define ELF_CLASS ELFCLASS32 #define ELF_DATA ELFDATA2MSB; +#define elf_check_arch(x) (((x) == EM_SPARC) || ((x) == EM_SPARC32PLUS)) + #include #include #include diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.1.43/linux/arch/sparc64/kernel/etrap.S Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/etrap.S Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.21 1997/06/02 06:33:28 davem Exp $ +/* $Id: etrap.S,v 1.22 1997/06/13 14:02:40 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -59,7 +59,10 @@ sethi %uhi(KERNBASE), %g3 sllx %g3, 32, %g3 mov PRIMARY_CONTEXT, %g2 - stxa %g0, [%g2] ASI_DMMU + ldxa [%g2] ASI_DMMU, %g6 + stxa %g0, [%g2] ASI_DMMU ! XXX fixup cache if this stays... + mov SECONDARY_CONTEXT, %g2 + stxa %g6, [%g2] ASI_DMMU flush %g3 2: wrpr %g0, 0x0, %tl diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.43/linux/arch/sparc64/kernel/ioctl32.c Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/ioctl32.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.8 1997/06/04 13:05:15 jj Exp $ +/* $Id: ioctl32.c,v 1.11 1997/06/16 11:05:00 jj Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -20,9 +20,15 @@ #include #include #include +#include +#include #include #include +#include +#include +#include +#include /* As gcc will warn about casting u32 to some ptr, we have to cast it to * unsigned long first, and that's what is A() for. @@ -370,6 +376,109 @@ return err; } +struct fbcmap32 { + int index; /* first element (0 origin) */ + int count; + u32 red; + u32 green; + u32 blue; +}; + +#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) +#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) + +static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg) +{ + struct fbcmap f; + int ret; + char red[256], green[256], blue[256]; + u32 r, g, b; + unsigned long old_fs = get_fs(); + + if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) || + __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) || + __get_user(r, &(((struct fbcmap32 *)A(arg))->red)) || + __get_user(g, &(((struct fbcmap32 *)A(arg))->green)) || + __get_user(b, &(((struct fbcmap32 *)A(arg))->blue))) + return -EFAULT; + if ((f.index < 0) || (f.index > 255)) return -EINVAL; + if (f.index + f.count > 256) + f.count = 256 - f.index; + if (cmd == FBIOPUTCMAP32) { + if (copy_from_user (red, (char *)A(r), f.count) || + copy_from_user (green, (char *)A(g), f.count) || + copy_from_user (blue, (char *)A(b), f.count)) + return -EFAULT; + } + f.red = red; f.green = green; f.blue = blue; + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP : FBIOGETCMAP, (long)&f); + set_fs (old_fs); + if (!ret && cmd == FBIOGETCMAP32) { + if (copy_to_user ((char *)A(r), red, f.count) || + copy_to_user ((char *)A(g), green, f.count) || + copy_to_user ((char *)A(b), blue, f.count)) + return -EFAULT; + } + return ret; +} + +struct fbcursor32 { + short set; /* what to set, choose from the list above */ + short enable; /* cursor on/off */ + struct fbcurpos pos; /* cursor position */ + struct fbcurpos hot; /* cursor hot spot */ + struct fbcmap32 cmap; /* color map info */ + struct fbcurpos size; /* cursor bit map size */ + u32 image; /* cursor image bits */ + u32 mask; /* cursor mask bits */ +}; + +#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) +#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) + +static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg) +{ + struct fbcursor f; + int ret; + char red[2], green[2], blue[2]; + char image[128], mask[128]; + u32 r, g, b; + u32 m, i; + unsigned long old_fs = get_fs(); + + if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) || + __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) || + __get_user(f.size.fby, &(((struct fbcursor32 *)A(arg))->size.fby)) || + __get_user(f.cmap.index, &(((struct fbcursor32 *)A(arg))->cmap.index)) || + __get_user(f.cmap.count, &(((struct fbcursor32 *)A(arg))->cmap.count)) || + __get_user(r, &(((struct fbcursor32 *)A(arg))->cmap.red)) || + __get_user(g, &(((struct fbcursor32 *)A(arg))->cmap.green)) || + __get_user(b, &(((struct fbcursor32 *)A(arg))->cmap.blue)) || + __get_user(m, &(((struct fbcursor32 *)A(arg))->mask)) || + __get_user(i, &(((struct fbcursor32 *)A(arg))->image))) + return -EFAULT; + if (f.set & FB_CUR_SETCMAP) { + if ((uint) f.size.fby > 32) + return -EINVAL; + if (copy_from_user (mask, (char *)A(m), f.size.fby * 4) || + copy_from_user (image, (char *)A(i), f.size.fby * 4)) + return -EFAULT; + f.image = image; f.mask = mask; + } + if (f.set & FB_CUR_SETCMAP) { + if (copy_from_user (red, (char *)A(r), 2) || + copy_from_user (green, (char *)A(g), 2) || + copy_from_user (blue, (char *)A(b), 2)) + return -EFAULT; + f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue; + } + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f); + set_fs (old_fs); + return ret; +} + asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg) { struct file * filp; @@ -431,6 +540,15 @@ case BLKGETSIZE: error = w_long(fd, cmd, arg); goto out; + + case FBIOPUTCMAP32: + case FBIOGETCMAP32: + error = fbiogetputcmap(fd, cmd, arg); + goto out; + + case FBIOSCURSOR32: + error = fbiogscursor(fd, cmd, arg); + goto out; /* List here exlicitly which ioctl's are known to have * compatable types passed or none at all... @@ -471,6 +589,17 @@ case TIOCSPGRP: case TIOCGPGRP: case TIOCSCTTY: + + /* Big F */ + case FBIOGTYPE: + case FBIOSATTR: + case FBIOGATTR: + case FBIOSVIDEO: + case FBIOGVIDEO: + case FBIOGCURSOR32: /* This is not implemented yet. Later it should be converted... */ + case FBIOSCURPOS: + case FBIOGCURPOS: + case FBIOGCURMAX: /* Little f */ case FIOCLEX: @@ -479,6 +608,10 @@ case FIONBIO: case FIONREAD: /* This is also TIOCINQ */ + /* 0x00 */ + case FIBMAP: + case FIGETBSZ: + /* 0x12 */ case BLKRRPART: case BLKFLSBUF: @@ -495,6 +628,59 @@ case KDSIGACCEPT: case KDGETKEYCODE: case KDSETKEYCODE: + case KIOCSOUND: + case KDMKTONE: + case KDGKBTYPE: + case KDSETMODE: + case KDGETMODE: + case KDSKBMODE: + case KDGKBMODE: + case KDSKBMETA: + case KDGKBMETA: + case KDGKBENT: + case KDSKBENT: + case KDGKBSENT: + case KDSKBSENT: + case KDGKBDIACR: + case KDSKBDIACR: + case KDGKBLED: + case KDSKBLED: + case KDGETLED: + case KDSETLED: + + /* Little k */ + case KIOCTYPE: + case KIOCLAYOUT: + case KIOCGTRANS: + case KIOCTRANS: + case KIOCCMD: + case KIOCSDIRECT: + case KIOCSLED: + case KIOCGLED: + case KIOCSRATE: + case KIOCGRATE: + + /* Big V */ + case VT_SETMODE: + case VT_GETMODE: + case VT_GETSTATE: + case VT_OPENQRY: + case VT_ACTIVATE: + case VT_WAITACTIVE: + case VT_RELDISP: + case VT_DISALLOCATE: + case VT_RESIZE: + case VT_RESIZEX: + case VT_LOCKSWITCH: + case VT_UNLOCKSWITCH: + + /* Little v */ + case VUIDSFORMAT: + case VUIDGFORMAT: + + /* Little p (/dev/rtc etc.) */ + case RTCGET: + case RTCSET: /* Socket level stuff */ case FIOSETOWN: diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.1.43/linux/arch/sparc64/kernel/process.c Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/process.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $ +/* $Id: process.c,v 1.18 1997/06/13 14:02:42 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -360,6 +360,7 @@ } /* Now, this task is no longer a kernel thread. */ + current->tss.current_ds = USER_DS; if(current->tss.flags & SPARC_FLAG_KTHREAD) { current->tss.flags &= ~SPARC_FLAG_KTHREAD; @@ -368,8 +369,8 @@ */ get_mmu_context(current); } - current->tss.current_ds = USER_DS; - spitfire_set_secondary_context (current->mm->context); + current->tss.ctx = current->mm->context & 0x1fff; + spitfire_set_secondary_context (current->tss.ctx); } static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src) @@ -571,12 +572,13 @@ childregs->u_regs[UREG_FP] = p->tss.ksp; p->tss.flags |= SPARC_FLAG_KTHREAD; p->tss.current_ds = KERNEL_DS; + p->tss.ctx = 0; childregs->u_regs[UREG_G6] = (unsigned long) p; } else { childregs->u_regs[UREG_FP] = sp; p->tss.flags &= ~SPARC_FLAG_KTHREAD; p->tss.current_ds = USER_DS; - + p->tss.ctx = (p->mm->context & 0x1fff); #if 0 if (sp != regs->u_regs[UREG_FP]) { struct sparc_stackf *childstack; diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.1.43/linux/arch/sparc64/kernel/rtrap.S Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/rtrap.S Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.21 1997/06/02 07:26:54 davem Exp $ +/* $Id: rtrap.S,v 1.23 1997/06/16 07:38:41 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -25,10 +25,10 @@ or %l2, %lo(bh_active), %l2 sethi %hi(bh_mask), %l1 or %l1, %lo(bh_mask), %l1 - ldx [%l2 + %g4], %l3 - ldx [%l1 + %g4], %l4 + ldx [%l2 + %g4], %l4 + ldx [%l1 + %g4], %l7 - andcc %l3, %l4, %g0 + andcc %l4, %l7, %g0 be,pt %xcc, 2f nop call do_bottom_half diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.1.43/linux/arch/sparc64/kernel/signal.c Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/signal.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.6 1997/05/29 12:44:48 jj Exp $ +/* $Id: signal.c,v 1.7 1997/06/16 06:49:59 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -144,19 +144,21 @@ } #endif synchronize_user_stack (); - sf = (struct new_signal_frame *) regs->u_regs [UREG_FP]; + sf = (struct new_signal_frame *) + (regs->u_regs [UREG_FP] + STACK_BIAS); + /* 1. Make sure we are not getting garbage from the user */ - if (verify_area (VERIFY_READ, sf, sizeof (*sf))){ + if (verify_area (VERIFY_READ, sf, sizeof (*sf))) goto segv; - } - if (((unsigned long) sf) & 3){ + + if (((unsigned long) sf) & 3) goto segv; - } + get_user(tpc, &sf->info.si_regs.tpc); __get_user(tnpc, &sf->info.si_regs.tnpc); - if ((tpc | tnpc) & 3){ + if ((tpc | tnpc) & 3) goto segv; - } + regs->tpc = tpc; regs->tnpc = tnpc; @@ -229,14 +231,15 @@ if (!current->used_math) sigframe_size -= sizeof(__siginfo_fpu_t); - sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size); + sf = (struct new_signal_frame *) + (regs->u_regs[UREG_FP] + STACK_BIAS - sigframe_size); - if (invalid_frame_pointer (sf, sigframe_size)){ + if (invalid_frame_pointer (sf, sigframe_size)) { lock_kernel (); do_exit(SIGILL); } - if (current->tss.w_saved != 0){ + if (current->tss.w_saved != 0) { printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); lock_kernel (); @@ -254,8 +257,8 @@ } __put_user(oldmask, &sf->info.si_mask); - for (i = 0; i < sizeof(struct reg_window)/8; i++) { - __get_user(tmp, (((u64 *)regs->u_regs[UREG_FP])+i)); + for (i = 0; i < sizeof(struct reg_window)/sizeof(u64); i++) { + __get_user(tmp, (((u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS))+i)); __put_user(tmp, (((u64 *)sf)+i)); } @@ -264,7 +267,7 @@ __put_user(0x91d02011, &sf->insns[1]); /* t 0x11 */ /* 4. signal handler back-trampoline and parameters */ - regs->u_regs[UREG_FP] = (unsigned long) sf; + regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.1.43/linux/arch/sparc64/kernel/sys_sparc32.c Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/sys_sparc32.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $ +/* $Id: sys_sparc32.c,v 1.32 1997/06/17 05:36:40 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1327,13 +1327,162 @@ return sys_umount((char *)A(name)); } +struct ncp_mount_data32 { + int version; + unsigned int ncp_fd; + __kernel_uid_t32 mounted_uid; + __kernel_pid_t32 wdog_pid; + unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; + unsigned int time_out; + unsigned int retry_count; + unsigned int flags; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_mode_t32 file_mode; + __kernel_mode_t32 dir_mode; +}; + +static void *do_ncp_super_data_conv(void *raw_data) +{ + struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data; + struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data; + + n->dir_mode = n32->dir_mode; + n->file_mode = n32->file_mode; + n->gid = n32->gid; + n->uid = n32->uid; + memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int))); + n->wdog_pid = n32->wdog_pid; + n->mounted_uid = n32->mounted_uid; + return raw_data; +} + +struct smb_mount_data32 { + int version; + unsigned int fd; + __kernel_uid_t32 mounted_uid; + struct sockaddr_in addr; + char server_name[17]; + char client_name[17]; + char service[64]; + char root_path[64]; + char username[64]; + char password[64]; + char domain[64]; + unsigned short max_xmit; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_mode_t32 file_mode; + __kernel_mode_t32 dir_mode; +}; + +static void *do_smb_super_data_conv(void *raw_data) +{ + struct smb_mount_data *s = (struct smb_mount_data *)raw_data; + struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data; + + s->dir_mode = s32->dir_mode; + s->file_mode = s32->file_mode; + s->gid = s32->gid; + s->uid = s32->uid; + memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr))); + s->mounted_uid = s32->mounted_uid; + return raw_data; +} + +static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) +{ + int i; + unsigned long page; + struct vm_area_struct *vma; + + *kernel = 0; + if(!user) + return 0; + vma = find_vma(current->mm, (unsigned long)user); + if(!vma || (unsigned long)user < vma->vm_start) + return -EFAULT; + if(!(vma->vm_flags & VM_READ)) + return -EFAULT; + i = vma->vm_end - (unsigned long) user; + if(PAGE_SIZE <= (unsigned long) i) + i = PAGE_SIZE - 1; + if(!(page = __get_free_page(GFP_KERNEL))) + return -ENOMEM; + if(copy_from_user((void *) page, user, i)) { + free_page(page); + return -EFAULT; + } + *kernel = page; + return 0; +} + extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data); +#define SMBFS_NAME "smbfs" +#define NCPFS_NAME "ncpfs" + asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data) { - return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type), - (unsigned long)new_flags, (void *)A(data)); + unsigned long type_page; + int err, is_smb, is_ncp; + + if(!suser()) + return -EPERM; + is_smb = is_ncp = 0; + err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page); + if(err) + return err; + if(type_page) { + is_smb = !strcmp((char *)type_page, SMBFS_NAME); + is_ncp = !strcmp((char *)type_page, NCPFS_NAME); + } + if(!is_smb && !is_ncp) { + if(type_page) + free_page(type_page); + return sys_mount((char *)A(dev_name), (char *)A(dir_name), + (char *)A(type), (unsigned long)new_flags, + (void *)A(data)); + } else { + unsigned long dev_page, dir_page, data_page; + int old_fs; + + err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page); + if(err) + goto out; + err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page); + if(err) + goto dev_out; + err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page); + if(err) + goto dir_out; + if(is_ncp) + do_ncp_super_data_conv((void *)data_page); + else if(is_smb) + do_smb_super_data_conv((void *)data_page); + else + panic("Tell DaveM he fucked up..."); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_mount((char *)dev_page, (char *)dir_page, + (char *)type_page, (unsigned long)new_flags, + (void *)data_page); + set_fs(old_fs); + + if(data_page) + free_page(data_page); + dir_out: + if(dir_page) + free_page(dir_page); + dev_out: + if(dev_page) + free_page(dev_page); + out: + if(type_page) + free_page(type_page); + return err; + } } extern asmlinkage int sys_syslog(int type, char * bug, int count); @@ -1598,6 +1747,31 @@ return sys_acct((const char *)A(name)); } +extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid); + +asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid) +{ + uid_t sruid, seuid; + + sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); + seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); + return sys_setreuid(sruid, seuid); +} + +extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); + +asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid, + __kernel_uid_t32 euid, + __kernel_uid_t32 suid) +{ + uid_t sruid, seuid, ssuid; + + sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); + seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); + ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid); + return sys_setresuid(sruid, seuid, ssuid); +} + extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid) @@ -1654,7 +1828,7 @@ set_fs (KERNEL_DS); ret = sys_getgroups(gidsetsize, gl); set_fs (old_fs); - if (ret > 0 && ret <= NGROUPS) + if (gidsetsize && ret > 0 && ret <= NGROUPS) for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32)) if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist))) return -EFAULT; @@ -1716,6 +1890,9 @@ return sys_setdomainname((char *)A(name), len); } +#define RLIM_INFINITY32 0x7fffffff +#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) + struct rlimit32 { s32 rlim_cur; s32 rlim_max; @@ -1733,8 +1910,8 @@ ret = sys_getrlimit(resource, &r); set_fs (old_fs); if (!ret && ( - put_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) || - __put_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max)))) + put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) || + __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max)))) return -EFAULT; return ret; } @@ -1751,6 +1928,10 @@ if (get_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) || __get_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max))) return -EFAULT; + if (r.rlim_cur == RLIM_INFINITY32) + r.rlim_cur = RLIM_INFINITY; + if (r.rlim_max == RLIM_INFINITY32) + r.rlim_max = RLIM_INFINITY; set_fs (KERNEL_DS); ret = sys_setrlimit(resource, &r); set_fs (old_fs); @@ -2557,67 +2738,4 @@ asmlinkage int sys32_no_modules(void) { return -ENOSYS; -} - -struct ncp_mount_data32 { - int version; - unsigned int ncp_fd; - __kernel_uid_t32 mounted_uid; - __kernel_pid_t32 wdog_pid; - unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; - unsigned int time_out; - unsigned int retry_count; - unsigned int flags; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; -}; - -void *do_ncp_super_data_conv(void *raw_data) -{ - struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data; - struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data; - - n->dir_mode = n32->dir_mode; - n->file_mode = n32->file_mode; - n->gid = n32->gid; - n->uid = n32->uid; - memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int))); - n->wdog_pid = n32->wdog_pid; - n->mounted_uid = n32->mounted_uid; - return raw_data; -} - -struct smb_mount_data32 { - int version; - unsigned int fd; - __kernel_uid_t32 mounted_uid; - struct sockaddr_in addr; - char server_name[17]; - char client_name[17]; - char service[64]; - char root_path[64]; - char username[64]; - char password[64]; - char domain[64]; - unsigned short max_xmit; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; -}; - -void *do_smb_super_data_conv(void *raw_data) -{ - struct smb_mount_data *s = (struct smb_mount_data *)raw_data; - struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data; - - s->dir_mode = s32->dir_mode; - s->file_mode = s32->file_mode; - s->gid = s32->gid; - s->uid = s32->uid; - memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr))); - s->mounted_uid = s32->mounted_uid; - return raw_data; } diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.1.43/linux/arch/sparc64/kernel/systbls.S Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/kernel/systbls.S Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.13 1997/06/04 13:05:29 jj Exp $ +/* $Id: systbls.S,v 1.16 1997/06/16 05:37:41 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -30,7 +30,7 @@ /*50*/ .xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve /*60*/ .xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize - .xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .xword sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*70*/ .xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups /*80*/ .xword sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall @@ -42,7 +42,7 @@ /*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .xword sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall /*120*/ .xword sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod - .xword sys_nis_syscall, sys_setreuid, sys_setregid, sys32_rename, sys32_truncate + .xword sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate /*130*/ .xword sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .xword sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall /*140*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit @@ -94,18 +94,18 @@ /*80*/ .xword sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall .xword sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .xword sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall - .xword sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*100*/ .xword sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_nis_syscall + .xword sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept +/*100*/ .xword sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind + .xword sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg + .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall /*120*/ .xword sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod - .xword sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall -/*140*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit + .xword sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate +/*130*/ .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown + .xword sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall +/*140*/ .xword sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit .xword sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*150*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*150*/ .xword sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .xword sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount /*160*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall .xword sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall @@ -116,7 +116,7 @@ /*190*/ .xword sys_init_module, sys_personality, sys_prof, sys_break, sys_lock .xword sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask /*200*/ .xword sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall - .xword sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall + .xword sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall /*210*/ .xword sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo .xword sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex /*220*/ .xword sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c --- v2.1.43/linux/arch/sparc64/kernel/unaligned.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/unaligned.c Thu Jun 26 12:33:38 1997 @@ -0,0 +1,517 @@ +/* $Id: unaligned.c,v 1.1 1997/06/06 10:56:19 jj Exp $ + * unaligned.c: Unaligned load/store trap handling with special + * cases for the kernel to do them more quickly. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_MNA + +enum direction { + load, /* ld, ldd, ldh, ldsh */ + store, /* st, std, sth, stsh */ + both, /* Swap, ldstub, cas, ... */ + fpload, + fpstore, + invalid, +}; + +#ifdef DEBUG_MNA +static char *dirstrings[] = { + "load", "store", "both", "fpload", "fpstore", "invalid" +}; +#endif + +static inline enum direction decode_direction(unsigned int insn) +{ + unsigned long tmp = (insn >> 21) & 1; + + if(!tmp) + return load; + else { + switch ((insn>>19)&0xf) { + case 15: /* swap* */ + return both; + default: + return store; + } + } +} + +/* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ +static inline int decode_access_size(unsigned int insn) +{ + unsigned int tmp; + + if (((insn >> 19) & 0xf) == 14) + return 8; /* stx* */ + tmp = (insn >> 19) & 3; + if(!tmp) + return 4; + else if(tmp == 3) + return 16; /* ldd/std - Although it is actually 8 */ + else if(tmp == 2) + return 2; + else { + printk("Impossible unaligned trap. insn=%08x\n", insn); + die_if_kernel("Byte sized unaligned access?!?!", current->tss.kregs); + } +} + +static inline int decode_asi(unsigned int insn, struct pt_regs *regs) +{ + if (insn & 0x800000) { + if (insn & 0x2000) + return (unsigned char)(regs->tstate >> 24); /* %asi */ + else + return (unsigned char)(insn >> 5); /* imm_asi */ + } else + return ASI_P; +} + +/* 0x400000 = signed, 0 = unsigned */ +static inline int decode_signedness(unsigned int insn) +{ + return (insn & 0x400000); +} + +static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, + unsigned int rd) +{ + if(rs2 >= 16 || rs1 >= 16 || rd >= 16) { + flushw_user(); + } +} + +static inline long sign_extend_imm13(long imm) +{ + return imm << 51 >> 51; +} + +static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) +{ + struct reg_window *win; + + if(reg < 16) + return (!reg ? 0 : regs->u_regs[reg]); + + /* Ho hum, the slightly complicated case. */ + win = (struct reg_window *) regs->u_regs[UREG_FP]; + return win->locals[reg - 16]; /* yes, I know what this does... */ +} + +static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) +{ + struct reg_window *win; + + if(reg < 16) + return ®s->u_regs[reg]; + win = (struct reg_window *) regs->u_regs[UREG_FP]; + return &win->locals[reg - 16]; +} + +static inline unsigned long compute_effective_address(struct pt_regs *regs, + unsigned int insn) +{ + unsigned int rs1 = (insn >> 14) & 0x1f; + unsigned int rs2 = insn & 0x1f; + unsigned int rd = (insn >> 25) & 0x1f; + + if(insn & 0x2000) { + maybe_flush_windows(rs1, 0, rd); + return (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); + } else { + maybe_flush_windows(rs1, rs2, rd); + return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); + } +} + +/* This is just to make gcc think panic does return... */ +static void unaligned_panic(char *str) +{ + panic(str); +} + +#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({ \ +__asm__ __volatile__ ( \ + "wr %4, 0, %%asi\n\t" \ + "cmp %1, 8\n\t" \ + "bge,pn %%icc, 9f\n\t" \ + " cmp %1, 4\n\t" \ + "be,pt %%icc, 6f\n" \ +"4:\t" " lduba [%2] %%asi, %%l1\n" \ +"5:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sll %%l1, 8, %%l1\n\t" \ + "brz,pt %3, 3f\n\t" \ + " add %%l1, %%l2, %%l1\n\t" \ + "sllx %%l1, 48, %%l1\n\t" \ + "srax %%l1, 48, %%l1\n" \ +"3:\t" "ba,pt %%xcc, 0f\n\t" \ + " stx %%l1, [%0]\n" \ +"6:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sll %%l1, 24, %%l1\n" \ +"7:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \ + "sll %%l2, 16, %%l2\n" \ +"8:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \ + "sll %%g7, 8, %%g7\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n\t" \ + "or %%l1, %%g7, %%l1\n\t" \ + "brnz,a,pt %3, 3f\n\t" \ + " sra %%l1, 0, %%l1\n" \ +"3:\t" "ba,pt %%xcc, 0f\n\t" \ + " stx %%l1, [%0]\n" \ +"9:\t" "lduba [%2] %%asi, %%l1\n" \ +"10:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \ + "sllx %%l1, 56, %%l1\n" \ +"11:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \ + "sllx %%l2, 48, %%l2\n" \ +"12:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \ + "sllx %%g7, 40, %%g7\n\t" \ + "sllx %%g1, 32, %%g1\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n" \ +"13:\t" "lduba [%2 + 4] %%asi, %%l2\n\t" \ + "or %%l1, %%g7, %%g7\n" \ +"14:\t" "lduba [%2 + 5] %%asi, %%g1\n\t" \ + "sllx %%l2, 24, %%l2\n" \ +"15:\t" "lduba [%2 + 6] %%asi, %%l1\n\t" \ + "sllx %%g1, 16, %%g1\n\t" \ + "or %%g7, %%l2, %%g7\n" \ +"16:\t" "lduba [%2 + 7] %%asi, %%l2\n\t" \ + "sllx %%l1, 8, %%l1\n\t" \ + "or %%g7, %%g1, %%g7\n\t" \ + "or %%l1, %%l2, %%l1\n\t" \ + "or %%g7, %%l1, %%g7\n\t" \ + "cmp %1, 8\n\t" \ + "be,a,pt %%icc, 0f\n\t" \ + " stx %%g7, [%0]\n\t" \ + "srlx %%g7, 32, %%l1\n\t" \ + "sra %%g7, 0, %%g7\n\t" \ + "stx %%l1, [%0]\n\t" \ + "stx %%g7, [%0 + 8]\n" \ +"0:\n\n\t" \ + ".section __ex_table\n\t" \ + ".word 4b, " #errh "\n\t" \ + ".word 5b, " #errh "\n\t" \ + ".word 6b, " #errh "\n\t" \ + ".word 7b, " #errh "\n\t" \ + ".word 8b, " #errh "\n\t" \ + ".word 9b, " #errh "\n\t" \ + ".word 10b, " #errh "\n\t" \ + ".word 11b, " #errh "\n\t" \ + ".word 12b, " #errh "\n\t" \ + ".word 13b, " #errh "\n\t" \ + ".word 14b, " #errh "\n\t" \ + ".word 15b, " #errh "\n\t" \ + ".word 16b, " #errh "\n\n\t" \ + ".previous\n\t" \ + : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), "r" (asi) \ + : "l1", "l2", "g7", "g1", "cc"); \ +}) + +#define store_common(dst_addr, size, src_val, asi, errh) ({ \ +__asm__ __volatile__ ( \ + "wr %3, 0, %%asi\n\t" \ + "ldx [%2], %%l1\n" \ + "cmp %1, 2\n\t" \ + "be,pn %%icc, 2f\n\t" \ + " cmp %1, 4\n\t" \ + "be,pt %%icc, 1f\n\t" \ + " srlx %%l1, 24, %%l2\n\t" \ + "srlx %%l1, 56, %%g1\n\t" \ + "srlx %%l1, 48, %%g7\n" \ +"4:\t" "stba %%g1, [%0] %%asi\n\t" \ + "srlx %%l1, 40, %%g1\n" \ +"5:\t" "stba %%g7, [%0 + 1] %%asi\n\t" \ + "srlx %%l1, 32, %%g7\n" \ +"6:\t" "stba %%g1, [%0 + 2] %%asi\n" \ +"7:\t" "stba %%g7, [%0 + 3] %%asi\n\t" \ + "srlx %%l1, 16, %%g1\n" \ +"8:\t" "stba %%l2, [%0 + 4] %%asi\n\t" \ + "srlx %%l1, 8, %%g7\n" \ +"9:\t" "stba %%g1, [%0 + 5] %%asi\n" \ +"10:\t" "stba %%g7, [%0 + 6] %%asi\n\t" \ + "ba,pt %%xcc, 0f\n" \ +"11:\t" " stba %%l1, [%0 + 7] %%asi\n" \ +"1:\t" "srl %%l1, 16, %%g7\n" \ +"12:\t" "stba %%l2, [%0] %%asi\n\t" \ + "srl %%l1, 8, %%l2\n" \ +"13:\t" "stba %%g7, [%0 + 1] %%asi\n" \ +"14:\t" "stba %%l2, [%0 + 2] %%asi\n\t" \ + "ba,pt %%xcc, 0f\n" \ +"15:\t" " stba %%l1, [%0 + 3] %%asi\n" \ +"2:\t" "srl %%l1, 8, %%l2\n" \ +"16:\t" "stba %%l2, [%0] %%asi\n" \ +"17:\t" "stba %%l1, [%0 + 1] %%asi\n" \ +"0:\n\n\t" \ + ".section __ex_table\n\t" \ + ".word 4b, " #errh "\n\t" \ + ".word 5b, " #errh "\n\t" \ + ".word 6b, " #errh "\n\t" \ + ".word 7b, " #errh "\n\t" \ + ".word 8b, " #errh "\n\t" \ + ".word 9b, " #errh "\n\t" \ + ".word 10b, " #errh "\n\t" \ + ".word 11b, " #errh "\n\t" \ + ".word 12b, " #errh "\n\t" \ + ".word 13b, " #errh "\n\t" \ + ".word 14b, " #errh "\n\t" \ + ".word 15b, " #errh "\n\t" \ + ".word 16b, " #errh "\n\t" \ + ".word 17b, " #errh "\n\n\t" \ + ".previous\n\t" \ + : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi) \ + : "l1", "l2", "g7", "g1", "cc"); \ +}) + +#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({ \ + unsigned long zero = 0; \ + unsigned long *src_val = &zero; \ + \ + if (size == 16) { \ + size = 8; \ + zero = (((long)(reg_num ? \ + (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | \ + (unsigned)fetch_reg(reg_num + 1, regs); \ + } else if (reg_num) src_val = fetch_reg_addr(reg_num, regs); \ + store_common(dst_addr, size, src_val, asi, errh); \ +}) + +/* XXX Need to capture/release other cpu's for SMP around this. */ +#define do_atomic(srcdest_reg, mem, errh) ({ \ + unsigned long flags, tmp; \ + \ + save_and_cli(flags); \ + tmp = *srcdest_reg; \ + do_integer_load(srcdest_reg, 4, mem, 0, errh); \ + store_common(mem, 4, &tmp, errh); \ + restore_flags(flags); \ +}) + +static inline void advance(struct pt_regs *regs) +{ + regs->tpc = regs->tnpc; + regs->tnpc += 4; +} + +static inline int floating_point_load_or_store_p(unsigned int insn) +{ + return (insn >> 24) & 1; +} + +static inline int ok_for_kernel(unsigned int insn) +{ + return !floating_point_load_or_store_p(insn); +} + +void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault"); + +void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) +{ + unsigned long g2 = regs->u_regs [UREG_G2]; + unsigned long fixup = search_exception_table (regs->tpc, &g2); + + if (!fixup) { + unsigned long address = compute_effective_address(regs, insn); + if(address < PAGE_SIZE) { + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler"); + } else + printk(KERN_ALERT "Unable to handle kernel paging request in mna handler"); + printk(KERN_ALERT " at virtual address %016lx\n",address); + printk(KERN_ALERT "current->mm->context = %016lx\n", + (unsigned long) current->mm->context); + printk(KERN_ALERT "current->mm->pgd = %016lx\n", + (unsigned long) current->mm->pgd); + die_if_kernel("Oops", regs); + /* Not reached */ + } + regs->tpc = fixup; + regs->tnpc = regs->tpc + 4; + regs->u_regs [UREG_G2] = g2; +} + +asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) +{ + enum direction dir = decode_direction(insn); + int size = decode_access_size(insn); + + lock_kernel(); + if(!ok_for_kernel(insn) || dir == both) { + printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n", + regs->tpc); + unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store."); + + __asm__ __volatile__ ("\n" +"kernel_unaligned_trap_fault:\n\t" + "mov %0, %%o0\n\t" + "call kernel_mna_trap_fault\n\t" + " mov %1, %%o1\n\t" + : + : "r" (regs), "r" (insn) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "g1", "g2", "g3", "g4", "g5", "g7", "cc"); + } else { + unsigned long addr = compute_effective_address(regs, insn); + +#ifdef DEBUG_MNA + printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n", + regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); +#endif + switch(dir) { + case load: + do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs), + size, (unsigned long *) addr, + decode_signedness(insn), decode_asi(insn, regs), + kernel_unaligned_trap_fault); + break; + + case store: + do_integer_store(((insn>>25)&0x1f), size, + (unsigned long *) addr, regs, + decode_asi(insn, regs), + kernel_unaligned_trap_fault); + break; +#if 0 /* unsupported */ + case both: + do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs), + (unsigned long *) addr, + kernel_unaligned_trap_fault); + break; +#endif + default: + panic("Impossible kernel unaligned trap."); + /* Not reached... */ + } + advance(regs); + } + unlock_kernel(); +} + +#if 0 /* XXX: Implement user mna some day */ +static inline int ok_for_user(struct pt_regs *regs, unsigned int insn, + enum direction dir) +{ + unsigned int reg; + int retval, check = (dir == load) ? VERIFY_READ : VERIFY_WRITE; + int size = ((insn >> 19) & 3) == 3 ? 8 : 4; + + if((regs->pc | regs->npc) & 3) + return 0; + + /* Must verify_area() in all the necessary places. */ +#define WINREG_ADDR(regnum) ((void *)(((unsigned long *)regs->u_regs[UREG_FP])+(regnum))) + retval = 0; + reg = (insn >> 25) & 0x1f; + if(reg >= 16) { + retval = verify_area(check, WINREG_ADDR(reg - 16), size); + if(retval) + return retval; + } + reg = (insn >> 14) & 0x1f; + if(reg >= 16) { + retval = verify_area(check, WINREG_ADDR(reg - 16), size); + if(retval) + return retval; + } + if(!(insn & 0x2000)) { + reg = (insn & 0x1f); + if(reg >= 16) { + retval = verify_area(check, WINREG_ADDR(reg - 16), size); + if(retval) + return retval; + } + } + return retval; +#undef WINREG_ADDR +} + +void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("user_mna_trap_fault"); + +void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) +{ + current->tss.sig_address = regs->pc; + current->tss.sig_desc = SUBSIG_PRIVINST; + send_sig(SIGBUS, current, 1); +} + +asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) +{ + enum direction dir; + + lock_kernel(); + if(!(current->tss.flags & SPARC_FLAG_UNALIGNED) || + (((insn >> 30) & 3) != 3)) + goto kill_user; + dir = decode_direction(insn); + if(!ok_for_user(regs, insn, dir)) { + goto kill_user; + } else { + int size = decode_access_size(insn); + unsigned long addr; + + if(floating_point_load_or_store_p(insn)) { + printk("User FPU load/store unaligned unsupported.\n"); + goto kill_user; + } + + addr = compute_effective_address(regs, insn); + switch(dir) { + case load: + do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs), + size, (unsigned long *) addr, + decode_signedness(insn), + user_unaligned_trap_fault); + break; + + case store: + do_integer_store(((insn>>25)&0x1f), size, + (unsigned long *) addr, regs, + user_unaligned_trap_fault); + break; + + case both: + do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs), + (unsigned long *) addr, + user_unaligned_trap_fault); + break; + + default: + unaligned_panic("Impossible user unaligned trap."); + + __asm__ __volatile__ ("\n" +"user_unaligned_trap_fault:\n\t" + "mov %0, %%o0\n\t" + "call user_mna_trap_fault\n\t" + " mov %1, %%o1\n\t" + : + : "r" (regs), "r" (insn) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "g1", "g2", "g3", "g4", "g5", "g7", "cc"); + goto out; + } + advance(regs); + goto out; + } + +kill_user: + current->tss.sig_address = regs->pc; + current->tss.sig_desc = SUBSIG_PRIVINST; + send_sig(SIGBUS, current, 1); +out: + unlock_kernel(); +} +#endif diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.1.43/linux/arch/sparc64/lib/blockops.S Sat May 24 09:10:23 1997 +++ linux/arch/sparc64/lib/blockops.S Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.6 1997/05/18 04:16:49 davem Exp $ +/* $Id: blockops.S,v 1.7 1997/06/14 21:27:55 davem Exp $ * arch/sparc64/lib/blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -7,6 +7,8 @@ #include +#undef VIS_BLOCKOPS + /* Zero out 256 bytes of memory at (buf + offset). */ #define BLAST_BLOCK(buf, offset) \ stda %f48, [buf + offset + 0x00] %asi; \ @@ -31,9 +33,9 @@ .text .align 4 -#if 0 - .globl bzero_1page -bzero_1page: +#ifdef VIS_BLOCKOPS + .globl __bzero_1page +__bzero_1page: /* %o0 = buf */ mov %o0, %o1 wr %g0, ASI_BLK_P, %asi @@ -60,6 +62,36 @@ retl mov %o1, %o0 +#else +#define BZERO_256BYTES(base) \ + stx %g0, [base + 0x00]; stx %g0, [base + 0x08]; \ + stx %g0, [base + 0x10]; stx %g0, [base + 0x18]; \ + stx %g0, [base + 0x20]; stx %g0, [base + 0x28]; \ + stx %g0, [base + 0x30]; stx %g0, [base + 0x38]; \ + stx %g0, [base + 0x40]; stx %g0, [base + 0x48]; \ + stx %g0, [base + 0x50]; stx %g0, [base + 0x58]; \ + stx %g0, [base + 0x60]; stx %g0, [base + 0x68]; \ + stx %g0, [base + 0x70]; stx %g0, [base + 0x78]; \ + stx %g0, [base + 0x80]; stx %g0, [base + 0x88]; \ + stx %g0, [base + 0x90]; stx %g0, [base + 0x98]; \ + stx %g0, [base + 0xa0]; stx %g0, [base + 0xa8]; \ + stx %g0, [base + 0xb0]; stx %g0, [base + 0xb8]; \ + stx %g0, [base + 0xc0]; stx %g0, [base + 0xc8]; \ + stx %g0, [base + 0xd0]; stx %g0, [base + 0xd8]; \ + stx %g0, [base + 0xe0]; stx %g0, [base + 0xe8]; \ + stx %g0, [base + 0xf0]; stx %g0, [base + 0xf8]; + + .align 32 + .globl __bzero_1page +__bzero_1page: + mov 32, %g1 +1: + BZERO_256BYTES(%g2) + subcc %g1, 1, %g1 + bne,pt %icc, 1b + add %g2, 0x100, %g2 + jmpl %o7 + 0x8, %g0 + mov %g3, %o7 #endif .globl __bfill64 diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/memcpy.S linux/arch/sparc64/lib/memcpy.S --- v2.1.43/linux/arch/sparc64/lib/memcpy.S Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/lib/memcpy.S Thu Jun 26 12:33:38 1997 @@ -13,10 +13,10 @@ #ifdef __KERNEL__ -#define FUNC(x) \ - .globl x; \ - .type x,@function; \ - .align 4; \ +#define FUNC(x) \ + .globl x; \ + .type x,@function; \ + .align 4; \ x: #define FASTER_ALIGNED @@ -36,10 +36,10 @@ #define FASTER_ALIGNED #ifdef DEBUG -#define FUNC(x) \ - .globl jj##x##1; \ - .type jj##x##1,@function; \ - .align 4; \ +#define FUNC(x) \ + .globl jj##x##1; \ + .type jj##x##1,@function; \ + .align 4; \ jj##x##1: #else #include "DEFS.h" @@ -51,56 +51,56 @@ #endif -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - stw %t0, [%dst + offset + 0x00]; \ - stw %t1, [%dst + offset + 0x04]; \ - stw %t2, [%dst + offset + 0x08]; \ - stw %t3, [%dst + offset + 0x0c]; \ - stw %t4, [%dst + offset + 0x10]; \ - stw %t5, [%dst + offset + 0x14]; \ - stw %t6, [%dst + offset + 0x18]; \ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + ldd [%src + offset + 0x10], %t4; \ + ldd [%src + offset + 0x18], %t6; \ + stw %t0, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x04]; \ + stw %t2, [%dst + offset + 0x08]; \ + stw %t3, [%dst + offset + 0x0c]; \ + stw %t4, [%dst + offset + 0x10]; \ + stw %t5, [%dst + offset + 0x14]; \ + stw %t6, [%dst + offset + 0x18]; \ stw %t7, [%dst + offset + 0x1c]; -#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldx [%src + offset + 0x00], %t0; \ - ldx [%src + offset + 0x08], %t1; \ - ldx [%src + offset + 0x10], %t2; \ - ldx [%src + offset + 0x18], %t3; \ - ldx [%src + offset + 0x20], %t4; \ - ldx [%src + offset + 0x28], %t5; \ - ldx [%src + offset + 0x30], %t6; \ - ldx [%src + offset + 0x38], %t7; \ - stx %t0, [%dst + offset + 0x00]; \ - stx %t1, [%dst + offset + 0x08]; \ - stx %t2, [%dst + offset + 0x10]; \ - stx %t3, [%dst + offset + 0x18]; \ - stx %t4, [%dst + offset + 0x20]; \ - stx %t5, [%dst + offset + 0x28]; \ - stx %t6, [%dst + offset + 0x30]; \ +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + ldx [%src + offset + 0x10], %t2; \ + ldx [%src + offset + 0x18], %t3; \ + ldx [%src + offset + 0x20], %t4; \ + ldx [%src + offset + 0x28], %t5; \ + ldx [%src + offset + 0x30], %t6; \ + ldx [%src + offset + 0x38], %t7; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; \ + stx %t2, [%dst + offset + 0x10]; \ + stx %t3, [%dst + offset + 0x18]; \ + stx %t4, [%dst + offset + 0x20]; \ + stx %t5, [%dst + offset + 0x28]; \ + stx %t6, [%dst + offset + 0x30]; \ stx %t7, [%dst + offset + 0x38]; -#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - stw %t0, [%dst - offset - 0x10]; \ - stw %t1, [%dst - offset - 0x0c]; \ - stw %t2, [%dst - offset - 0x08]; \ +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - offset - 0x10], %t0; \ + ldd [%src - offset - 0x08], %t2; \ + stw %t0, [%dst - offset - 0x10]; \ + stw %t1, [%dst - offset - 0x0c]; \ + stw %t2, [%dst - offset - 0x08]; \ stw %t3, [%dst - offset - 0x04]; -#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ - ldx [%src - offset - 0x10], %t0; \ - ldx [%src - offset - 0x08], %t1; \ - stx %t0, [%dst - offset - 0x10]; \ +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src - offset - 0x10], %t0; \ + ldx [%src - offset - 0x08], %t1; \ + stx %t0, [%dst - offset - 0x10]; \ stx %t1, [%dst - offset - 0x08]; -#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src - offset - 0x02], %t0; \ - ldub [%src - offset - 0x01], %t1; \ - stb %t0, [%dst - offset - 0x02]; \ +#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src - offset - 0x02], %t0; \ + ldub [%src - offset - 0x01], %t1; \ + stb %t0, [%dst - offset - 0x02]; \ stb %t1, [%dst - offset - 0x01]; .text diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/lib/memset.S linux/arch/sparc64/lib/memset.S --- v2.1.43/linux/arch/sparc64/lib/memset.S Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/lib/memset.S Thu Jun 26 12:33:38 1997 @@ -31,7 +31,8 @@ /* Please don't change these macros, unless you change the logic * in the .fixup section below as well. - * Store 64 bytes at (BASE + OFFSET) using value SOURCE. */ + * Store 64 bytes at (BASE + OFFSET) using value SOURCE. + */ #define ZERO_BIG_BLOCK(base, offset, source) \ stxa source, [base + offset + 0x00] %asi; \ stxa source, [base + offset + 0x08] %asi; \ diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.1.43/linux/arch/sparc64/mm/fault.c Mon Jun 16 16:35:54 1997 +++ linux/arch/sparc64/mm/fault.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.11 1997/06/01 05:46:15 davem Exp $ +/* $Id: fault.c,v 1.12 1997/06/13 14:02:52 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -137,6 +137,13 @@ /* #define FAULT_TRACER */ /* #define FAULT_TRACER_VERBOSE */ +#ifdef FAULT_TRACER +/* Set and clear this elsewhere at critical moment, for oodles of debugging fun. */ +int fault_trace_enable = 0; +#endif + +#include + asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address, unsigned long tag, unsigned long sfsr) @@ -151,26 +158,36 @@ static unsigned long last_addr = 0; static int rcnt = 0; + if(fault_trace_enable) { #ifdef FAULT_TRACER_VERBOSE - printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...", - regs->tpc, text_fault, write, address); + printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...", + regs->tpc, text_fault, write, address); #else - printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write); + printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write); #endif - if(address == last_addr) { - if(rcnt++ > 15) { - printk("Wheee lotsa bogus faults, something wrong, spinning\n"); - __asm__ __volatile__("flushw"); - printk("o7[%016lx] i7[%016lx]\n", - regs->u_regs[UREG_I7], - ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]); - sti(); - while(1) - barrier(); - } - } else rcnt = 0; - last_addr = address; + if(address == last_addr) { + if(rcnt++ > 15) { + printk("Wheee lotsa bogus faults, something wrong, " + "spinning\n"); + printk("pctx[%016lx]sctx[%016lx]mmctx[%016lx]DS(%x)" + "tctx[%016lx] flgs[%016lx]\n", + spitfire_get_primary_context(), + spitfire_get_secondary_context(), + mm->context, (unsigned)current->tss.current_ds, + current->tss.ctx, current->tss.flags); + __asm__ __volatile__("flushw"); + printk("o7[%016lx] i7[%016lx]\n", + regs->u_regs[UREG_I7], + ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]); + sti(); + while(1) + barrier(); + } + } else rcnt = 0; + last_addr = address; + } #endif + lock_kernel (); down(&mm->mmap_sem); vma = find_vma(mm, address); @@ -233,11 +250,13 @@ out: unlock_kernel(); #ifdef FAULT_TRACER + if(fault_trace_enable) { #ifdef FAULT_TRACER_VERBOSE - printk(" done\n"); + printk(" done\n"); #else - printk("]"); + printk("]"); #endif + } #endif } diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.43/linux/arch/sparc64/mm/init.c Thu May 29 21:53:04 1997 +++ linux/arch/sparc64/mm/init.c Thu Jun 26 12:33:38 1997 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.29 1997/05/27 06:28:13 davem Exp $ +/* $Id: init.c,v 1.30 1997/06/06 10:56:21 jj Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -440,9 +440,9 @@ physaddr &= PAGE_MASK; if(rdonly) - pte = mk_pte_phys(physaddr, __pgprot(pg_iobits)); + pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __PRIV_BITS)); else - pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS)); + pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS | __PRIV_BITS)); set_pte(ptep, pte); } diff -u --recursive --new-file v2.1.43/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.43/linux/drivers/block/floppy.c Tue May 13 22:41:04 1997 +++ linux/drivers/block/floppy.c Sun Jun 29 10:51:09 1997 @@ -2896,6 +2896,8 @@ raw_cmd->flags |= FD_RAW_HARDFAILURE; } else { raw_cmd->reply_count = inr; + if(raw_cmd->reply_count > MAX_REPLIES) + raw_cmd->reply_count=0; for (i=0; i< raw_cmd->reply_count; i++) raw_cmd->reply[i] = reply_buffer[i]; diff -u --recursive --new-file v2.1.43/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.43/linux/drivers/block/ide.c Mon Jun 16 16:35:54 1997 +++ linux/drivers/block/ide.c Thu Jun 26 12:33:38 1997 @@ -2602,6 +2602,7 @@ ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1); ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0); ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0); + ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0); #endif /* CONFIG_BLK_DEV_TRITON */ #ifdef CONFIG_BLK_DEV_OPTI621 ide_probe_pci (PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, &ide_init_opti621, 0); diff -u --recursive --new-file v2.1.43/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v2.1.43/linux/drivers/block/ide.h Mon Jun 16 16:35:54 1997 +++ linux/drivers/block/ide.h Thu Jul 3 17:42:52 1997 @@ -298,7 +298,7 @@ typedef enum { ide_unknown, ide_generic, ide_triton, ide_cmd640, ide_dtc2278, ide_ali14xx, ide_qd6580, ide_umc8672, ide_ht6560b, - ide_promise } + ide_promise, ide_via } hwif_chipset_t; typedef struct hwif_s { diff -u --recursive --new-file v2.1.43/linux/drivers/block/triton.c linux/drivers/block/triton.c --- v2.1.43/linux/drivers/block/triton.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/triton.c Thu Jun 26 12:33:38 1997 @@ -122,15 +122,25 @@ #define PIIX_FLAGS_PREFETCH 4 #define PIIX_FLAGS_FAST_DMA 8 -typedef struct { - unsigned d0_flags :4; - unsigned d1_flags :4; - unsigned recovery :2; - unsigned reserved :2; - unsigned sample :2; - unsigned sidetim_enabled:1; - unsigned ports_enabled :1; -} piix_timing_t; + +union chip_en_reg_u { + struct { + unsigned d0_flags :4; + unsigned d1_flags :4; + unsigned recovery :2; + unsigned reserved :2; + unsigned sample :2; + unsigned sidetim_enabled:1; + unsigned ports_enabled :1; + } piix_s; + struct { + unsigned sec_en :1; + unsigned pri_en :1; + unsigned reserved :14; + } via_s; +}; + +typedef union chip_en_reg_u piix_timing_t; typedef struct { unsigned pri_recovery :2; @@ -269,16 +279,16 @@ printk("%s: pcibios read failed\n", HWIF(drive)->name); return 1; } - dflags = drive->select.b.unit ? timing.d1_flags : timing.d0_flags; + dflags = drive->select.b.unit ? timing.piix_s.d1_flags : timing.piix_s.d0_flags; if (dflags & PIIX_FLAGS_FAST_PIO) { if (func == ide_dma_on && drive->media == ide_disk) dflags |= PIIX_FLAGS_FAST_DMA; else dflags &= ~PIIX_FLAGS_FAST_DMA; if (drive->select.b.unit == 0) - timing.d0_flags = dflags; + timing.piix_s.d0_flags = dflags; else - timing.d1_flags = dflags; + timing.piix_s.d1_flags = dflags; if (pcibios_write_config_word(piix_pci_bus, piix_pci_fn, reg, *(short *)&timing)) { printk("%s: pcibios write failed\n", HWIF(drive)->name); return 1; @@ -456,8 +466,14 @@ chipset = "PIIX4"; else if (devid == PCI_DEVICE_ID_INTEL_82371SB_1) chipset = "PIIX3"; - else + else if (devid == PCI_DEVICE_ID_INTEL_82371_1) chipset = "PIIX"; + else if (devid == PCI_DEVICE_ID_VIA_82C586_1) + chipset = "VP1"; + else { + printk("Unknown PCI IDE interface 0x%x\n", devid); + goto quit; + } printk("%s: bus-master IDE device on PCI bus %d function %d\n", chipset, bus, fn); @@ -470,13 +486,24 @@ printk("%s: IDE ports are not enabled (BIOS)\n", chipset); goto quit; } - if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0]))) - goto quit; - if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1]))) - goto quit; - if ((!timings[0].ports_enabled) && (!timings[1].ports_enabled)) { - printk("%s: neither IDE port is enabled\n", chipset); - goto quit; + if (devid == PCI_DEVICE_ID_VIA_82C586_1) { + /* pri and sec channel enables are in port 0x40 */ + if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0]))) + goto quit; + if ((!timings[0].via_s.pri_en && (!timings[0].via_s.sec_en))) { + printk("%s: neither IDE port is enabled\n", chipset); + goto quit; + } + } + else { /* INTEL piix */ + if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0]))) + goto quit; + if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1]))) + goto quit; + if ((!timings[0].piix_s.ports_enabled) && (!timings[1].piix_s.ports_enabled)) { + printk("%s: neither IDE port is enabled\n", chipset); + goto quit; + } } /* @@ -526,10 +553,30 @@ case 0x170: pri_sec = 1; break; default: continue; } + + if (devid == PCI_DEVICE_ID_VIA_82C586_1) { + timing = timings[0]; + switch (h) { + case 0: + if (!timing.piix_s.ports_enabled) { + printk("port 0 DMA not enabled\n"); + continue; + } + case 1: + if (!timing.piix_s.sidetim_enabled) { + printk("port 1 DMA not enabled\n"); + continue; + } + } + hwif->chipset = ide_via; + } + else { /* PIIX */ + timing = timings[pri_sec]; - if (!timing.ports_enabled) /* interface disabled? */ + if (!timing.piix_s.ports_enabled) /* interface disabled? */ continue; hwif->chipset = ide_triton; + } if (dma_enabled) init_piix_dma(hwif, bmiba + (pri_sec ? 8 : 0)); #ifdef DISPLAY_PIIX_TIMINGS @@ -539,17 +586,32 @@ { const char *slave; piix_sidetim_t sidetim; - byte sample = 5 - timing.sample; - byte recovery = 4 - timing.recovery; + byte sample = 5 - timing.piix_s.sample; + byte recovery = 4 - timing.piix_s.recovery; + unsigned int drvtim; + + if (devid == PCI_DEVICE_ID_VIA_82C586_1) { + pcibios_read_config_dword(bus, fn, 0x48, &drvtim); + if (pri_sec == 0) { + printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+(drvtim>>28), 1+((drvtim & 0x0f000000)>>24)); + printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf00000)>>20), 1+((drvtim & 0x0f0000)>>16)); + continue; + } else { + printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf000)>>12), 1+((drvtim & 0x0f00)>>8)); + printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf0)>>4), 1+(drvtim & 0x0f)); + continue; + } + } + if ((devid == PCI_DEVICE_ID_INTEL_82371SB_1 || devid == PCI_DEVICE_ID_INTEL_82371AB) - && timing.sidetim_enabled + && timing.piix_s.sidetim_enabled && !pcibios_read_config_byte(bus, fn, 0x44, (byte *) &sidetim)) slave = ""; /* PIIX3 and later */ else slave = "/slave"; /* PIIX, or PIIX3 in compatibility mode */ printk(" %s master%s: sample_CLKs=%d, recovery_CLKs=%d\n", hwif->name, slave, sample, recovery); - print_piix_drive_flags ("master:", timing.d0_flags); + print_piix_drive_flags ("master:", timing.piix_s.d0_flags); if (!*slave) { if (pri_sec == 0) { sample = 5 - sidetim.pri_sample; @@ -560,7 +622,7 @@ } printk(" slave : sample_CLKs=%d, recovery_CLKs=%d\n", sample, recovery); } - print_piix_drive_flags ("slave :", timing.d1_flags); + print_piix_drive_flags ("slave :", timing.piix_s.d1_flags); } #endif /* DISPLAY_PIIX_TIMINGS */ } diff -u --recursive --new-file v2.1.43/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v2.1.43/linux/drivers/char/ChangeLog Tue Mar 4 10:25:23 1997 +++ linux/drivers/char/ChangeLog Thu Jun 26 12:33:38 1997 @@ -1,3 +1,27 @@ +Thu Jun 19 20:05:58 1997 Theodore Ts'o + + * serial.c (begin_break, end_break, rs_ioctl): Applied patch + to support BSD ioctls to set and clear the break + condition explicitly. + + * console.c (scrup, scrdown, insert_line, delete_line): Applied + fix suggested by Aaron Tiensivu to speed up block scrolls + up and down. + + * n_tty.c (opost_block, write_chan): Added a modified "fast + console" patch which processes a block of text via + "cooking" efficiently. + +Wed Jun 18 15:25:50 1997 Theodore Ts'o + + * tty_io.c (init_dev, release_dev): Applied fix suggested by Bill + Hawes to prevent race conditions in the tty code. + + * n_tty.c (n_tty_chars_in_buffer): Applied fix suggested by Bill + Hawes so that n_tty_chars_in_buffer returns the correct + value in the case when the tty is in cannonical mode. (To + avoid a pty deadlock with telnetd.) + Thu Feb 27 01:53:08 1997 Theodore Ts'o * serial.c (change_speed): Add support for the termios flag diff -u --recursive --new-file v2.1.43/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.1.43/linux/drivers/char/console.c Mon Jun 16 16:35:55 1997 +++ linux/drivers/char/console.c Thu Jun 26 12:33:38 1997 @@ -497,13 +497,15 @@ __set_origin(__real_origin); } -static void scrup(int currcons, unsigned int t, unsigned int b) +static void scrup(int currcons, unsigned int t, unsigned int b, unsigned int nr) { int hardscroll = hardscroll_enabled; - if (b > video_num_lines || t >= b) + if (t+nr >= b) + nr = b - t - 1; + if (b > video_num_lines || t >= b || nr < 1) return; - if (t || b != video_num_lines) + if (t || b != video_num_lines || nr > 1) hardscroll = 0; if (hardscroll) { origin += video_size_row; @@ -544,31 +546,35 @@ set_origin(currcons); } else { unsigned short * d = (unsigned short *) (origin+video_size_row*t); - unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1)); + unsigned short * s = (unsigned short *) (origin+video_size_row*(t+nr)); - memcpyw(d, s, (b-t-1) * video_size_row); - memsetw(d + (b-t-1) * video_num_columns, video_erase_char, video_size_row); + memcpyw(d, s, (b-t-nr) * video_size_row); + memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr); } } static void -scrdown(int currcons, unsigned int t, unsigned int b) +scrdown(int currcons, unsigned int t, unsigned int b, unsigned int nr) { unsigned short *s; unsigned int count; + unsigned int step; - if (b > video_num_lines || t >= b) + if (t+nr >= b) + nr = b - t - 1; + if (b > video_num_lines || t >= b || nr < 1) return; - s = (unsigned short *) (origin+video_size_row*(b-2)); - if (b >= t + 1) { - count = b - t - 1; - while (count) { - count--; - memcpyw(s + video_num_columns, s, video_size_row); - s -= video_num_columns; - } + s = (unsigned short *) (origin+video_size_row*(b-nr-1)); + step = video_num_columns * nr; + count = b - t - nr; + while (count--) { + memcpyw(s + step, s, video_size_row); + s -= video_num_columns; + } + while (nr--) { + s += video_num_columns; + memsetw(s, video_erase_char, video_size_row); } - memsetw(s + video_num_columns, video_erase_char, video_size_row); has_scrolled = 1; } @@ -578,7 +584,7 @@ * if below scrolling region */ if (y+1 == bottom) - scrup(currcons,top,bottom); + scrup(currcons,top,bottom, 1); else if (y < video_num_lines-1) { y++; pos += video_size_row; @@ -592,7 +598,7 @@ * if above scrolling region */ if (y == top) - scrdown(currcons,top,bottom); + scrdown(currcons,top,bottom,1); else if (y > 0) { y--; pos -= video_size_row; @@ -1117,9 +1123,9 @@ need_wrap = 0; } -static void insert_line(int currcons) +static void insert_line(int currcons, unsigned int nr) { - scrdown(currcons,y,bottom); + scrdown(currcons,y,bottom,nr); need_wrap = 0; } @@ -1136,9 +1142,9 @@ need_wrap = 0; } -static void delete_line(int currcons) +static void delete_line(int currcons, unsigned int nr) { - scrup(currcons,y,bottom); + scrup(currcons,y,bottom,nr); need_wrap = 0; } @@ -1158,8 +1164,7 @@ nr = video_num_lines; else if (!nr) nr = 1; - while (nr--) - insert_line(currcons); + insert_line(currcons, nr); } static void csi_P(int currcons, unsigned int nr) @@ -1178,8 +1183,7 @@ nr = video_num_lines; else if (!nr) nr=1; - while (nr--) - delete_line(currcons); + delete_line(currcons, nr); } static void save_cur(int currcons) diff -u --recursive --new-file v2.1.43/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.1.43/linux/drivers/char/n_tty.c Tue May 13 22:41:07 1997 +++ linux/drivers/char/n_tty.c Thu Jun 26 12:33:38 1997 @@ -88,9 +88,17 @@ /* * Return number of characters buffered to be delivered to user + * */ int n_tty_chars_in_buffer(struct tty_struct *tty) { + if (tty->icanon) { + if (!tty->canon_data) return 0; + + return (tty->canon_head > tty->read_tail) ? + tty->canon_head - tty->read_tail : + tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail); + } return tty->read_cnt; } @@ -157,6 +165,72 @@ return 0; } +/* + * opost_block --- to speed up block console writes, among other + * things. + */ +static int opost_block(struct tty_struct * tty, + const unsigned char * inbuf, unsigned int nr) +{ + char buf[80]; + int space; + int i; + char *cp; + + space = tty->driver.write_room(tty); + if (!space) + return 0; + if (nr > space) + nr = space; + if (nr > sizeof(buf)) + nr = sizeof(buf); + nr -= copy_from_user(buf, inbuf, nr); + if (!nr) + return 0; + + for (i = 0, cp = buf; i < nr; i++, cp++) { + switch (*cp) { + case '\n': + if (O_ONLRET(tty)) + tty->column = 0; + if (O_ONLCR(tty)) + goto break_out; + tty->canon_column = tty->column; + break; + case '\r': + if (O_ONOCR(tty) && tty->column == 0) + goto break_out; + if (O_OCRNL(tty)) { + *cp = '\n'; + if (O_ONLRET(tty)) + tty->canon_column = tty->column = 0; + break; + } + tty->canon_column = tty->column = 0; + break; + case '\t': + goto break_out; + case '\b': + if (tty->column > 0) + tty->column--; + break; + default: + if (O_OLCUC(tty)) + *cp = toupper(*cp); + if (!iscntrl(*cp)) + tty->column++; + break; + } + } +break_out: + if (tty->driver.flush_chars) + tty->driver.flush_chars(tty); + i = tty->driver.write(tty, 0, buf, i); + return i; +} + + + static inline void put_char(unsigned char c, struct tty_struct *tty) { tty->driver.put_char(tty, c); @@ -934,7 +1008,7 @@ const unsigned char * buf, unsigned int nr) { struct wait_queue wait = { current, NULL }; - int c; + int c, num; const unsigned char *b = buf; int retval = 0; @@ -958,6 +1032,11 @@ } if (O_OPOST(tty) && !(tty->flags & (1< 0) { + num = opost_block(tty, b, nr); + b += num; + nr -= num; + if (nr == 0) + break; get_user(c, b); if (opost(c, tty) < 0) break; diff -u --recursive --new-file v2.1.43/linux/drivers/char/psaux.c linux/drivers/char/psaux.c --- v2.1.43/linux/drivers/char/psaux.c Mon Jun 16 16:35:55 1997 +++ linux/drivers/char/psaux.c Fri Jul 4 23:33:56 1997 @@ -628,7 +628,10 @@ poll_aux_status_nosleep(); #endif /* INITIALIZE_DEVICE */ outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */ - aux_write_dev_nosleep(AUX_INTS_OFF); /* Disable controller interrupts */ + poll_aux_status_nosleep(); + outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG); + poll_aux_status_nosleep(); + outb_p(AUX_INTS_OFF, KBD_DATA_REG); } return 0; } diff -u --recursive --new-file v2.1.43/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.1.43/linux/drivers/char/pty.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/pty.c Sat Jun 28 10:31:36 1997 @@ -26,20 +26,6 @@ #define PTY_MAGIC 0x5001 -#define PTY_BUF_SIZE PAGE_SIZE/2 - -/* - * tmp_buf is used as a temporary buffer by pty_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a pty write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the PTY's, since it significantly saves memory if - * large numbers of PTY's are open. - */ -static unsigned char *tmp_buf; -static struct semaphore tmp_buf_sem = MUTEX; - static struct tty_driver pty_driver, pty_slave_driver; static struct tty_driver old_pty_driver, old_pty_slave_driver; static int pty_refcount; @@ -104,37 +90,51 @@ set_bit(TTY_THROTTLED, &tty->flags); } +/* + * WSH 05/24/97: modified to + * (1) use space in tty->flip instead of a shared temp buffer + * The flip buffers aren't being used for a pty, so there's lots + * of space available. The buffer is protected by a per-pty + * semaphore that should almost never come under contention. + * (2) avoid redundant copying for cases where count >> receive_room + * N.B. Calls from user space may now return an error code instead of + * a count. + */ static int pty_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c=0, n, r; + int c=0, n; char *temp_buffer; if (!to || tty->stopped) return 0; - + if (from_user) { - down(&tmp_buf_sem); - temp_buffer = tmp_buf + - ((tty->driver.subtype-1) * PTY_BUF_SIZE); + down(&tty->flip.pty_sem); + temp_buffer = &tty->flip.char_buf[0]; while (count > 0) { - n = MIN(count, PTY_BUF_SIZE); + /* check space so we don't copy needlessly */ + n = MIN(count, to->ldisc.receive_room(to)); + if (!n) break; + + n = MIN(n, PTY_BUF_SIZE); n -= copy_from_user(temp_buffer, buf, n); if (!n) { if (!c) c = -EFAULT; break; } - r = to->ldisc.receive_room(to); - if (r <= 0) - break; - n = MIN(n, r); - to->ldisc.receive_buf(to, temp_buffer, 0, n); - buf += n; c+= n; + + /* check again in case the buffer filled up */ + n = MIN(n, to->ldisc.receive_room(to)); + if (!n) break; + buf += n; + c += n; count -= n; + to->ldisc.receive_buf(to, temp_buffer, 0, n); } - up(&tmp_buf_sem); + up(&tty->flip.pty_sem); } else { c = MIN(count, to->ldisc.receive_room(to)); to->ldisc.receive_buf(to, buf, 0, c); @@ -153,14 +153,42 @@ return to->ldisc.receive_room(to); } +/* + * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior + * The chars_in_buffer() value is used by the ldisc select() function + * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). + * The pty driver chars_in_buffer() Master/Slave must behave differently: + * + * The Master side needs to allow typed-ahead commands to accumulate + * while being canonicalized, so we report "our buffer" as empty until + * some threshold is reached, and then report the count. (Any count > + * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock + * the count returned must be 0 if no canonical data is available to be + * read. (The N_TTY ldisc.chars_in_buffer now knows this.) + * + * The Slave side passes all characters in raw mode to the Master side's + * buffer where they can be read immediately, so in this case we can + * return the true count in the buffer. + */ static int pty_chars_in_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; + int count; if (!to || !to->ldisc.chars_in_buffer) return 0; - return to->ldisc.chars_in_buffer(to); + /* The ldisc must report 0 if no characters available to be read */ + count = to->ldisc.chars_in_buffer(to); + + if (tty->driver.subtype == PTY_TYPE_SLAVE) return count; + + /* Master side driver ... if the other side's read buffer is less than + * half full, return 0 to allow writers to proceed; otherwise return + * the count. This leaves a comfortable margin to avoid overflow, + * and still allows half a buffer's worth of typed-ahead commands. + */ + return ((count < N_TTY_BUF_SIZE/2) ? 0 : count); } static void pty_flush_buffer(struct tty_struct *tty) @@ -194,17 +222,6 @@ pty = pty_state + line; tty->driver_data = pty; - if (!tmp_buf) { - unsigned long page = __get_free_page(GFP_KERNEL); - if (!tmp_buf) { - retval = -ENOMEM; - if (!page) - goto out; - tmp_buf = (unsigned char *) page; - memset((void *) page, 0, PAGE_SIZE); - } else - free_page(page); - } retval = -EIO; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) goto out; @@ -287,8 +304,6 @@ old_pty_slave_driver.minor_start = 192; old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS; old_pty_slave_driver.other = &old_pty_driver; - - tmp_buf = 0; if (tty_register_driver(&pty_driver)) panic("Couldn't register pty driver"); diff -u --recursive --new-file v2.1.43/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.1.43/linux/drivers/char/random.c Tue May 13 22:41:07 1997 +++ linux/drivers/char/random.c Thu Jun 26 12:33:39 1997 @@ -1,7 +1,7 @@ /* * random.c -- A strong random number generator * - * Version 1.02, last modified 15-Apr-97 + * Version 1.03, last modified 26-Apr-97 * * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997. All rights reserved. * @@ -1335,11 +1335,15 @@ * starting point for each pair of TCP endpoints. This defeats * attacks which rely on guessing the initial TCP sequence number. * This algorithm was suggested by Steve Bellovin. + * + * Using a very strong hash was taking an appreciable amount of the total + * TCP connection establishment time, so this is a weaker hash, + * compensated for by changing the secret periodically. */ /* F, G and H are basic MD4 functions: selection, majority, parity */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) @@ -1357,9 +1361,9 @@ (a) = ROTL ((s), (a));} /* - * Basic cut-down MD4 transform + * Basic cut-down MD4 transform. Returns only 32 bits of result. */ -static void halfMD4Transform (__u32 buf[4], __u32 in[8]) +static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8]) { __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; @@ -1376,77 +1380,141 @@ /* Round 2 */ GG (a, b, c, d, in[ 0], 3); GG (d, a, b, c, in[ 4], 5); - GG (a, b, c, d, in[ 1], 9); - GG (d, a, b, c, in[ 5], 13); + GG (c, d, a, b, in[ 1], 9); + GG (b, c, d, a, in[ 5], 13); GG (a, b, c, d, in[ 2], 3); GG (d, a, b, c, in[ 6], 5); - GG (a, b, c, d, in[ 3], 9); - GG (d, a, b, c, in[ 7], 13); + GG (c, d, a, b, in[ 3], 9); + GG (b, c, d, a, in[ 7], 13); /* Round 3 */ HH (a, b, c, d, in[ 0], 3); - HH (c, d, a, b, in[ 4], 9); - HH (a, b, c, d, in[ 2], 11); - HH (c, d, a, b, in[ 6], 15); + HH (d, a, b, c, in[ 4], 9); + HH (c, d, a, b, in[ 2], 11); + HH (b, c, d, a, in[ 6], 15); HH (a, b, c, d, in[ 1], 3); - HH (c, d, a, b, in[ 5], 9); - HH (a, b, c, d, in[ 3], 11); - HH (c, d, a, b, in[ 7], 15); + HH (d, a, b, c, in[ 5], 9); + HH (c, d, a, b, in[ 3], 11); + HH (b, c, d, a, in[ 7], 15); - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; + return buf[1] + b; /* "most hashed" word */ + /* Alternative: return sum of all words? */ } +/* This should not be decreased so low that ISNs wrap too fast. */ #define REKEY_INTERVAL 300 +#define HASH_BITS 24 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport) { static __u32 rekey_time = 0; + static __u32 count = 0; static __u32 secret[12]; - static char count = 0; struct timeval tv; - __u32 tmp[12]; __u32 seq; /* - * Pick a random secret every REKEY_INTERVAL seconds + * Pick a random secret every REKEY_INTERVAL seconds. */ - do_gettimeofday(&tv); + do_gettimeofday(&tv); /* We need the usecs below... */ + if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) { - get_random_bytes(&secret, sizeof(secret)); rekey_time = tv.tv_sec; - count++; + /* First three words are overwritten below. */ + get_random_bytes(&secret+3, sizeof(secret)-12); + count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS; } - memcpy(tmp, secret, sizeof(tmp)); /* - * Pick a unique starting offset for each - * TCP connection endpoints (saddr, daddr, sport, dport) + * Pick a unique starting offset for each TCP connection endpoints + * (saddr, daddr, sport, dport). + * Note that the words are placed into the first words to be + * mixed in with the halfMD4. This is because the starting + * vector is also a random secret (at secret+8), and further + * hashing fixed data into it isn't going to improve anything, + * so we should get started with the variable data. */ - tmp[8]=saddr; - tmp[9]=daddr; - tmp[10]=(sport << 16) + dport; - halfMD4Transform(tmp, tmp+4); - + secret[0]=saddr; + secret[1]=daddr; + secret[2]=(sport << 16) + dport; + + seq = (halfMD4Transform(secret+8, secret) & + ((1<state = TASK_RUNNING; diff -u --recursive --new-file v2.1.43/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.1.43/linux/drivers/char/serial.c Tue May 13 22:41:07 1997 +++ linux/drivers/char/serial.c Thu Jun 26 12:33:39 1997 @@ -1328,6 +1328,9 @@ info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2; #endif + /* disable break condition */ + serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); serial_outp(info, UART_MCR, info->MCR); @@ -1996,6 +1999,30 @@ } /* + * This routine sets the break condition on the serial port. + */ +static void begin_break(struct async_struct * info) +{ + if (!info->port) + return; + cli(); + serial_out(info, UART_LCR, serial_inp(info, UART_LCR) | UART_LCR_SBC); + sti(); +} + +/* + * This routine clears the break condition on the serial port. + */ +static void end_break(struct async_struct * info) +{ + if (!info->port) + return; + cli(); + serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); + sti(); +} + +/* * This routine returns a bitfield of "wild interrupts". Basically, * any unclaimed interrupts which is flapping around. */ @@ -2198,6 +2225,19 @@ send_break(info, arg ? arg*(HZ/10) : HZ/4); if (current->signal & ~current->blocked) return -EINTR; + return 0; + case TIOCSBRK: + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + begin_break(info); + return 0; + case TIOCCBRK: + retval = tty_check_change(tty); + if (retval) + return retval; + end_break(info); return 0; case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); diff -u --recursive --new-file v2.1.43/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.43/linux/drivers/char/tty_io.c Mon Jun 16 16:35:55 1997 +++ linux/drivers/char/tty_io.c Sat Jun 28 10:31:36 1997 @@ -45,9 +45,12 @@ * Restrict vt switching via ioctl() * -- grif@cs.ucr.edu, 5-Dec-95 * - * Move console and virtual terminal code to more apropriate files, + * Move console and virtual terminal code to more appropriate files, * implement CONFIG_VT and generalize console device interface. * -- Marko Kohtala , March 97 + * + * Rewrote init_dev and release_dev to eliminate races. + * -- Bill Hawes , June 97 */ #include @@ -90,8 +93,8 @@ #undef TTY_DEBUG_HANGUP -#define TTY_PARANOIA_CHECK -#define CHECK_TTY_COUNT +#define TTY_PARANOIA_CHECK 1 +#define CHECK_TTY_COUNT 1 struct termios tty_std_termios; /* for the benefit of tty drivers */ struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */ @@ -651,18 +654,31 @@ (unsigned int)count); } +/* Semaphore to protect creating and releasing a tty */ +static struct semaphore tty_sem = MUTEX; +static void down_tty_sem(int index) +{ + down(&tty_sem); +} +static void up_tty_sem(int index) +{ + up(&tty_sem); +} +static void release_mem(struct tty_struct *tty, int idx); + /* - * This is so ripe with races that you should *really* not touch this - * unless you know exactly what you are doing. All the changes have to be - * made atomically, or there may be incorrect pointers all over the place. + * WSH 06/09/97: Rewritten to remove races and properly clean up after a + * failed open. The new code protects the open with a semaphore, so it's + * really quite straightforward. The semaphore locking can probably be + * relaxed for the (most common) case of reopening a tty. */ static int init_dev(kdev_t device, struct tty_struct **ret_tty) { - struct tty_struct *tty, **tty_loc, *o_tty, **o_tty_loc; + struct tty_struct *tty, *o_tty; struct termios *tp, **tp_loc, *o_tp, **o_tp_loc; struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; struct tty_driver *driver; - int retval; + int retval=0; int idx; driver = get_tty_driver(device); @@ -670,175 +686,236 @@ return -ENODEV; idx = MINOR(device) - driver->minor_start; - tty = o_tty = NULL; + tty = driver->table[idx]; + + /* + * Check whether we need to acquire the tty semaphore to avoid + * race conditions. For now, play it safe. + */ + down_tty_sem(idx); + + /* check whether we're reopening an existing tty */ + if(tty) goto fast_track; + + /* + * First time open is complex, especially for PTY devices. + * This code guarantees that either everything succeeds and the + * TTY is ready for operation, or else the table slots are vacated + * and the allocated memory released. (Except that the termios + * and locked termios may be retained.) + */ + + o_tty = NULL; tp = o_tp = NULL; ltp = o_ltp = NULL; - o_tty_loc = NULL; - o_tp_loc = o_ltp_loc = NULL; - tty_loc = &driver->table[idx]; - tp_loc = &driver->termios[idx]; - ltp_loc = &driver->termios_locked[idx]; + tty = (struct tty_struct*) get_free_page(GFP_KERNEL); + if(!tty) + goto fail_no_mem; + initialize_tty_struct(tty); + tty->device = device; + tty->driver = *driver; -repeat: - retval = -EIO; - if (driver->type == TTY_DRIVER_TYPE_PTY && - driver->subtype == PTY_TYPE_MASTER && - *tty_loc && (*tty_loc)->count) - goto end_init; - retval = -ENOMEM; - if (!*tty_loc && !tty) { - if (!(tty = (struct tty_struct*) get_free_page(GFP_KERNEL))) - goto end_init; - initialize_tty_struct(tty); - tty->device = device; - tty->driver = *driver; - goto repeat; - } - if (!*tp_loc && !tp) { + tp_loc = &driver->termios[idx]; + if (!*tp_loc) { tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); if (!tp) - goto end_init; + goto free_mem_out; *tp = driver->init_termios; - goto repeat; } - if (!*ltp_loc && !ltp) { + + ltp_loc = &driver->termios_locked[idx]; + if (!*ltp_loc) { ltp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); if (!ltp) - goto end_init; + goto free_mem_out; memset(ltp, 0, sizeof(struct termios)); - goto repeat; } + if (driver->type == TTY_DRIVER_TYPE_PTY) { - o_tty_loc = &driver->other->table[idx]; - o_tp_loc = &driver->other->termios[idx]; - o_ltp_loc = &driver->other->termios_locked[idx]; + o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL); + if (!o_tty) + goto free_mem_out; + initialize_tty_struct(o_tty); + o_tty->device = (kdev_t) MKDEV(driver->other->major, + driver->other->minor_start + idx); + o_tty->driver = *driver->other; - if (!*o_tty_loc && !o_tty) { - kdev_t o_device; - - o_tty = (struct tty_struct *) - get_free_page(GFP_KERNEL); - if (!o_tty) - goto end_init; - o_device = MKDEV(driver->other->major, - driver->other->minor_start + idx); - initialize_tty_struct(o_tty); - o_tty->device = o_device; - o_tty->driver = *driver->other; - goto repeat; - } - if (!*o_tp_loc && !o_tp) { + o_tp_loc = &driver->other->termios[idx]; + if (!*o_tp_loc) { o_tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); if (!o_tp) - goto end_init; + goto free_mem_out; *o_tp = driver->other->init_termios; - goto repeat; } - if (!*o_ltp_loc && !o_ltp) { + + o_ltp_loc = &driver->other->termios_locked[idx]; + if (!*o_ltp_loc) { o_ltp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); if (!o_ltp) - goto end_init; + goto free_mem_out; memset(o_ltp, 0, sizeof(struct termios)); - goto repeat; } - + + /* + * Everything allocated ... set up the o_tty structure. + */ + driver->other->table[idx] = o_tty; + if (!*o_tp_loc) + *o_tp_loc = o_tp; + if (!*o_ltp_loc) + *o_ltp_loc = o_ltp; + o_tty->termios = *o_tp_loc; + o_tty->termios_locked = *o_ltp_loc; + (*driver->other->refcount)++; + if (driver->subtype == PTY_TYPE_MASTER) + o_tty->count++; + + /* Establish the links in both directions */ + tty->link = o_tty; + o_tty->link = tty; } - /* Now we have allocated all the structures: update all the pointers.. */ - if (!*tp_loc) { + + /* + * All structures have been allocated, so now we install them. + * Failures after this point use release_mem to clean up, so + * there's no need to null out the local pointers. + */ + driver->table[idx] = tty; + if (!*tp_loc) *tp_loc = tp; - tp = NULL; - } - if (!*ltp_loc) { + if (!*ltp_loc) *ltp_loc = ltp; - ltp = NULL; + tty->termios = *tp_loc; + tty->termios_locked = *ltp_loc; + (*driver->refcount)++; + tty->count++; + + /* + * Structures all installed ... call the ldisc open routines. + * If we fail here just call release_mem to clean up. No need + * to decrement the use counts, as release_mem doesn't care. + */ + if (tty->ldisc.open) { + retval = (tty->ldisc.open)(tty); + if (retval) + goto release_mem_out; } - if (!*tty_loc) { - tty->termios = *tp_loc; - tty->termios_locked = *ltp_loc; - *tty_loc = tty; - (*driver->refcount)++; - (*tty_loc)->count++; - if (tty->ldisc.open) { - retval = (tty->ldisc.open)(tty); - if (retval < 0) { - (*tty_loc)->count--; - tty = NULL; - goto end_init; - } - } - tty = NULL; - } else { - if ((*tty_loc)->flags & (1 << TTY_CLOSING)) { - printk("Attempt to open closing tty %s.\n", - tty_name(*tty_loc)); - printk("Ack!!!! This should never happen!!\n"); - return -EINVAL; + if (o_tty && o_tty->ldisc.open) { + retval = (o_tty->ldisc.open)(o_tty); + if (retval) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + goto release_mem_out; } - (*tty_loc)->count++; } - if (driver->type == TTY_DRIVER_TYPE_PTY) { - if (!*o_tp_loc) { - *o_tp_loc = o_tp; - o_tp = NULL; - } - if (!*o_ltp_loc) { - *o_ltp_loc = o_ltp; - o_ltp = NULL; - } - if (!*o_tty_loc) { - o_tty->termios = *o_tp_loc; - o_tty->termios_locked = *o_ltp_loc; - *o_tty_loc = o_tty; - (*driver->other->refcount)++; - if (o_tty->ldisc.open) { - retval = (o_tty->ldisc.open)(o_tty); - if (retval < 0) { - (*tty_loc)->count--; - o_tty = NULL; - goto end_init; - } - } - o_tty = NULL; + goto success; + + /* + * This fast open can be used if the tty is already open. + * No memory is allocated, and the only failures are from + * attempting to open a closing tty or attempting multiple + * opens on a pty master. + */ +fast_track: + if (tty->flags & (1 << TTY_CLOSING)) { + retval = -EIO; + goto end_init; + } + if (driver->type == TTY_DRIVER_TYPE_PTY && + driver->subtype == PTY_TYPE_MASTER) { + /* + * special case for PTY masters: only one open permitted, + * and the slave side open count is incremented as well. + */ + if (tty->count) { + retval = -EIO; + goto end_init; } - (*tty_loc)->link = *o_tty_loc; - (*o_tty_loc)->link = *tty_loc; - if (driver->subtype == PTY_TYPE_MASTER) - (*o_tty_loc)->count++; + tty->link->count++; } - (*tty_loc)->driver = *driver; - *ret_tty = *tty_loc; - retval = 0; + tty->count++; + tty->driver = *driver; /* N.B. why do this every time?? */ + +success: + *ret_tty = tty; + + /* All paths come through here to release the semaphore */ end_init: - if (tty) - free_page((unsigned long) tty); - if (o_tty) - free_page((unsigned long) o_tty); - if (tp) - kfree_s(tp, sizeof(struct termios)); + up_tty_sem(idx); + return retval; + + /* Release locally allocated memory ... nothing placed in slots */ +free_mem_out: if (o_tp) kfree_s(o_tp, sizeof(struct termios)); + if (o_tty) + free_page((unsigned long) o_tty); if (ltp) kfree_s(ltp, sizeof(struct termios)); - if (o_ltp) - kfree_s(o_ltp, sizeof(struct termios)); - return retval; + if (tp) + kfree_s(tp, sizeof(struct termios)); + free_page((unsigned long) tty); + +fail_no_mem: + retval = -ENOMEM; + goto end_init; + + /* call the tty release_mem routine to clean out this slot */ +release_mem_out: + printk("init_dev: ldisc open failed, clearing slot %d\n", idx); + release_mem(tty, idx); + goto end_init; +} + +/* + * Releases memory associated with a tty structure, and clears out the + * driver table slots. + */ +static void release_mem(struct tty_struct *tty, int idx) +{ + struct tty_struct *o_tty; + struct termios *tp; + + if ((o_tty = tty->link) != NULL) { + o_tty->driver.table[idx] = NULL; + if (o_tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { + tp = o_tty->driver.termios[idx]; + o_tty->driver.termios[idx] = NULL; + kfree_s(tp, sizeof(struct termios)); + } + o_tty->magic = 0; + (*o_tty->driver.refcount)--; + free_page((unsigned long) o_tty); + } + + tty->driver.table[idx] = NULL; + if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { + tp = tty->driver.termios[idx]; + tty->driver.termios[idx] = NULL; + kfree_s(tp, sizeof(struct termios)); + } + tty->magic = 0; + (*tty->driver.refcount)--; + free_page((unsigned long) tty); } /* * Even releasing the tty structures is a tricky business.. We have * to be very careful that the structures are all released at the * same time, as interrupts might otherwise get the wrong pointers. + * + * WSH 09/09/97: rewritten to avoid some nasty race conditions that could + * lead to double frees or releasing memory still in use. */ static void release_dev(struct file * filp) { struct tty_struct *tty, *o_tty; - struct termios *tp, *o_tp, *ltp, *o_ltp; - struct task_struct *p; + int pty_master, tty_closing, o_tty_closing, do_sleep; int idx; tty = (struct tty_struct *)filp->private_data; @@ -849,10 +926,11 @@ tty_fasync(filp->f_inode, filp, 0); - tp = tty->termios; - ltp = tty->termios_locked; - idx = MINOR(tty->device) - tty->driver.minor_start; + pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY && + tty->driver.subtype == PTY_TYPE_MASTER); + o_tty = tty->link; + #ifdef TTY_PARANOIA_CHECK if (idx < 0 || idx >= tty->driver.num) { printk("release_dev: bad idx when trying to free (%s)\n", @@ -864,15 +942,15 @@ idx, kdevname(tty->device)); return; } - if (tp != tty->driver.termios[idx]) { - printk("release_dev: driver.termios[%d] not termios for (" - "%s)\n", + if (tty->termios != tty->driver.termios[idx]) { + printk("release_dev: driver.termios[%d] not termios " + "for (%s)\n", idx, kdevname(tty->device)); return; } - if (ltp != tty->driver.termios_locked[idx]) { - printk("release_dev: driver.termios_locked[%d] not termios_locked for (" - "%s)\n", + if (tty->termios_locked != tty->driver.termios_locked[idx]) { + printk("release_dev: driver.termios_locked[%d] not " + "termios_locked for (%s)\n", idx, kdevname(tty->device)); return; } @@ -883,10 +961,6 @@ tty->count); #endif - o_tty = tty->link; - o_tp = (o_tty) ? o_tty->termios : NULL; - o_ltp = (o_tty) ? o_tty->termios_locked : NULL; - #ifdef TTY_PARANOIA_CHECK if (tty->driver.other) { if (o_tty != tty->driver.other->table[idx]) { @@ -895,34 +969,90 @@ idx, kdevname(tty->device)); return; } - if (o_tp != tty->driver.other->termios[idx]) { - printk("release_dev: other->termios[%d] not o_termios for (" - "%s)\n", + if (o_tty->termios != tty->driver.other->termios[idx]) { + printk("release_dev: other->termios[%d] not o_termios " + "for (%s)\n", idx, kdevname(tty->device)); return; } - if (o_ltp != tty->driver.other->termios_locked[idx]) { - printk("release_dev: other->termios_locked[%d] not o_termios_locked for (" - "%s)\n", + if (o_tty->termios_locked != + tty->driver.other->termios_locked[idx]) { + printk("release_dev: other->termios_locked[%d] not " + "o_termios_locked for (%s)\n", idx, kdevname(tty->device)); return; } - if (o_tty->link != tty) { printk("release_dev: bad pty pointers\n"); return; } } #endif - + /* + * Sanity check: if tty->count is going to zero, there shouldn't be + * any waiters on tty->read_wait or tty->write_wait. We test the + * wait queues and kick everyone out _before_ actually starting to + * close. This ensures that we won't block while releasing the tty + * structure. + * + * The test for the o_tty closing is necessary, since the master and + * slave sides may close in any order. If the slave side closes out + * first, its count will be one, since the master side holds an open. + * Thus this test wouldn't be triggered at the time the slave closes, + * so we do it now. + * + * Note that it's possible for the tty to be opened again while we're + * flushing out waiters. By recalculating the closing flags before + * each iteration we avoid any problems. + */ + while (1) { + tty_closing = tty->count <= 1; + o_tty_closing = o_tty && + (o_tty->count <= (pty_master ? 1 : 0)); + do_sleep = 0; + + if (tty_closing) { + if (waitqueue_active(&tty->read_wait)) { + wake_up(&tty->read_wait); + do_sleep++; + } + if (waitqueue_active(&tty->write_wait)) { + wake_up(&tty->write_wait); + do_sleep++; + } + } + if (o_tty_closing) { + if (waitqueue_active(&o_tty->read_wait)) { + wake_up(&o_tty->read_wait); + do_sleep++; + } + if (waitqueue_active(&o_tty->write_wait)) { + wake_up(&o_tty->write_wait); + do_sleep++; + } + } + if (!do_sleep) + break; + + printk("release_dev: %s: read/write wait queue active!\n", + tty_name(tty)); + schedule(); + } + + /* + * The closing flags are now consistent with the open counts on + * both sides, and we've completed the last operation that could + * block, so it's safe to proceed with closing. + */ + if (tty->driver.close) tty->driver.close(tty, filp); - if (tty->driver.type == TTY_DRIVER_TYPE_PTY && - tty->driver.subtype == PTY_TYPE_MASTER) { - if (--tty->link->count < 0) { + + if (pty_master) { + if (--o_tty->count < 0) { printk("release_dev: bad pty slave count (%d) for %s\n", - tty->count, tty_name(tty)); - tty->link->count = 0; + o_tty->count, tty_name(o_tty)); + o_tty->count = 0; } } if (--tty->count < 0) { @@ -930,60 +1060,50 @@ tty->count, tty_name(tty)); tty->count = 0; } - if (tty->count) - return; /* - * Sanity check --- if tty->count is zero, there shouldn't be - * any waiters on tty->read_wait or tty->write_wait. But just - * in case.... + * Perform some housekeeping before deciding whether to return. + * + * Set the TTY_CLOSING flag if this was the last open. In the + * case of a pty we may have to wait around for the other side + * to close, and TTY_CLOSING makes sure we can't be reopened. */ - while (1) { - if (waitqueue_active(&tty->read_wait)) { - printk("release_dev: %s: read_wait active?!?\n", - tty_name(tty)); - wake_up(&tty->read_wait); - } else if (waitqueue_active(&tty->write_wait)) { - printk("release_dev: %s: write_wait active?!?\n", - tty_name(tty)); - wake_up(&tty->write_wait); - } else - break; - schedule(); - } - + if(tty_closing) + tty->flags |= (1 << TTY_CLOSING); + if(o_tty_closing) + o_tty->flags |= (1 << TTY_CLOSING); + /* - * We're committed; at this point, we must not block! + * If _either_ side is closing, make sure there aren't any + * processes that still think tty or o_tty is their controlling + * tty. Also, clear redirect if it points to either tty. */ - if (o_tty) { - if (o_tty->count) - return; - tty->driver.other->table[idx] = NULL; - tty->driver.other->termios[idx] = NULL; - kfree_s(o_tp, sizeof(struct termios)); + if (tty_closing || o_tty_closing) { + struct task_struct *p; + + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->tty == tty || (o_tty && p->tty == o_tty)) + p->tty = NULL; + } + read_unlock(&tasklist_lock); + + if (redirect == tty || (o_tty && redirect == o_tty)) + redirect = NULL; } + + /* check whether both sides are closing ... */ + if (!tty_closing || (o_tty && !o_tty_closing)) + return; + filp->private_data = 0; #ifdef TTY_DEBUG_HANGUP printk("freeing tty structure..."); #endif - tty->flags |= (1 << TTY_CLOSING); /* - * Make sure there aren't any processes that still think this - * tty is their controlling tty. - */ - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->tty == tty) - p->tty = NULL; - if (o_tty && p->tty == o_tty) - p->tty = NULL; - } - read_unlock(&tasklist_lock); - - /* - * Shutdown the current line discipline, and reset it to - * N_TTY. + * Shutdown the current line discipline, and reset it to N_TTY. + * N.B. why reset ldisc when we're releasing the memory?? */ if (tty->ldisc.close) (tty->ldisc.close)(tty); @@ -995,41 +1115,34 @@ o_tty->ldisc = ldiscs[N_TTY]; } - tty->driver.table[idx] = NULL; - if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { - tty->driver.termios[idx] = NULL; - kfree_s(tp, sizeof(struct termios)); - } - if (tty == redirect || o_tty == redirect) - redirect = NULL; /* * Make sure that the tty's task queue isn't activated. If it - * is, take it out of the linked list. + * is, take it out of the linked list. The tqueue isn't used by + * pty's, so skip the test for them. */ - spin_lock_irq(&tqueue_lock); - if (tty->flip.tqueue.sync) { - struct tq_struct *tq, *prev; - - for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) { - if (tq == &tty->flip.tqueue) { - if (prev) - prev->next = tq->next; - else - tq_timer = tq->next; - break; + if (tty->driver.type != TTY_DRIVER_TYPE_PTY) { + spin_lock_irq(&tqueue_lock); + if (tty->flip.tqueue.sync) { + struct tq_struct *tq, *prev; + + for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) { + if (tq == &tty->flip.tqueue) { + if (prev) + prev->next = tq->next; + else + tq_timer = tq->next; + break; + } } } + spin_unlock_irq(&tqueue_lock); } - spin_unlock_irq(&tqueue_lock); - tty->magic = 0; - (*tty->driver.refcount)--; - free_page((unsigned long) tty); - filp->private_data = 0; - if (o_tty) { - o_tty->magic = 0; - (*o_tty->driver.refcount)--; - free_page((unsigned long) o_tty); - } + + /* + * The release_mem function takes care of the details of clearing + * the slots and preserving the termios structure. + */ + release_mem(tty, idx); } /* @@ -1077,6 +1190,7 @@ retval = init_dev(device, &tty); if (retval) return retval; + /* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */ filp->private_data = tty; check_tty_count(tty, "tty_open"); if (tty->driver.type == TTY_DRIVER_TYPE_PTY && @@ -1123,11 +1237,6 @@ return 0; } -/* - * Note that releasing a pty master also releases the child, so - * we have to make the redirection checks after that and on both - * sides of a pty. - */ static int tty_release(struct inode * inode, struct file * filp) { release_dev(filp); @@ -1545,6 +1654,7 @@ tty->flip.flag_buf_ptr = tty->flip.flag_buf; tty->flip.tqueue.routine = flush_to_ldisc; tty->flip.tqueue.data = tty; + tty->flip.pty_sem = MUTEX; } /* diff -u --recursive --new-file v2.1.43/linux/drivers/isdn/sc/Makefile linux/drivers/isdn/sc/Makefile --- v2.1.43/linux/drivers/isdn/sc/Makefile Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/sc/Makefile Thu Jun 26 12:33:39 1997 @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.3 1997/05/27 23:25:01 fritz Exp $ +# $Id: Makefile,v 1.1 1997/03/22 02:01:22 fritz Exp $ # Copyright (C) 1996 SpellCaster Telecommunications Inc. # # This program is free software; you can redistribute it and/or modify diff -u --recursive --new-file v2.1.43/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.43/linux/drivers/net/Config.in Mon Jun 16 16:35:55 1997 +++ linux/drivers/net/Config.in Thu Jun 26 12:33:39 1997 @@ -15,6 +15,9 @@ # bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET if [ "$CONFIG_NET_ETHERNET" = "y" ]; then + if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then + bool 'MIPS JAZZ onboard SONIC ethernet support' CONFIG_MIPS_JAZZ_SONIC + fi bool '3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then tristate '3c501 support' CONFIG_EL1 @@ -110,7 +113,12 @@ # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_ATALK" != "n" ]; then - tristate 'LocalTalk PC support' CONFIG_LTPC + tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC + tristate 'COPS LocalTalk PC support' CONFIG_COPS + if [ "$CONFIG_COPS" != "n" ]; then + bool 'Dayna firmware support' CONFIG_COPS_DAYNA + bool 'Tangent firmware support' CONFIG_COPS_TANGENT + fi fi fi @@ -143,12 +151,8 @@ bool 'Soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8 bool 'Soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800 bool 'Soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600 - if [ -f drivers/net/soundmodem/sm_afsk2666.c ]; then - bool 'Soundmodem support for 2666 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK2666 - fi - if [ -f drivers/net/soundmodem/sm_psk4800.c ]; then - bool 'Soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800 - fi + #bool 'Soundmodem support for 2666 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK2666 + #bool 'Soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800 fi fi tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP diff -u --recursive --new-file v2.1.43/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.43/linux/drivers/net/Makefile Sun Apr 13 10:18:21 1997 +++ linux/drivers/net/Makefile Thu Jun 26 12:33:39 1997 @@ -275,6 +275,10 @@ endif endif +ifeq ($(CONFIG_SGISEEQ), y) +L_OBJS += sgiseeq.o +endif + ifeq ($(CONFIG_HAPPYMEAL),y) L_OBJS += sunhme.o else @@ -563,6 +567,14 @@ endif endif +ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y) +L_OBJS += sonic.o +else + ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m) + M_OBJS += sonic.o + endif +endif + ifeq ($(CONFIG_ATARILANCE),y) L_OBJS += atarilance.o else @@ -648,6 +660,14 @@ else ifeq ($(CONFIG_LTPC),m) M_OBJS += ltpc.o + endif +endif + +ifeq ($(CONFIG_COPS),y) +L_OBJS += cops.o +else + ifeq ($(CONFIG_COPS),m) + M_OBJS += cops.o endif endif diff -u --recursive --new-file v2.1.43/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.43/linux/drivers/net/Space.c Wed Apr 23 19:01:18 1997 +++ linux/drivers/net/Space.c Thu Jun 26 12:33:39 1997 @@ -74,6 +74,7 @@ extern int e2100_probe(struct device *); extern int ni52_probe(struct device *); extern int ni65_probe(struct device *); +extern int sonic_probe(struct device *); extern int SK_init(struct device *); extern int seeq8005_probe(struct device *); extern int tc59x_probe(struct device *); @@ -83,6 +84,7 @@ extern int happy_meal_probe(struct device *); extern int qec_probe(struct device *); extern int myri_sbus_probe(struct device *); +extern int sgiseeq_probe(struct device *); extern int atarilance_probe(struct device *); extern int a2065_probe(struct device *); extern int ariadne_probe(struct device *); @@ -241,7 +243,7 @@ && sparc_lance_probe(dev) #endif #ifdef CONFIG_HAPPYMEAL - && happy_meal_probe(dev) + && happy_meal_probe(dev) #endif #ifdef CONFIG_SUNQE && qec_probe(dev) @@ -249,6 +251,12 @@ #ifdef CONFIG_MYRI_SBUS && myri_sbus_probe(dev) #endif +#ifdef CONFIG_SGISEEQ + && sgiseeq_probe(dev) +#endif +#ifdef CONFIG_MIPS_JAZZ_SONIC + && sonic_probe(dev) +#endif && 1 ) { return 1; /* -ENODEV or -EAGAIN would be more accurate. */ } @@ -292,6 +300,17 @@ # undef NEXT_DEV # define NEXT_DEV (&dev_ltpc) #endif /* LTPC */ + +#if defined(CONFIG_COPS) + extern int cops_probe(struct device *); + static struct device dev_cops = { + "lt0", + 0, 0, 0, 0, + 0x0, 0, + 0, 0, 0, NEXT_DEV, cops_probe }; +# undef NEXT_DEV +# define NEXT_DEV (&dev_cops) +#endif /* COPS */ /* The first device defaults to I/O base '0', which means autoprobe. */ #ifndef ETH0_ADDR diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops.c linux/drivers/net/cops.c --- v2.1.43/linux/drivers/net/cops.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/cops.c Thu Jun 26 12:33:39 1997 @@ -0,0 +1,1016 @@ +/* cops.c: LocalTalk driver for Linux. + * + * Authors: + * - Jay Schulist + * + * With more than a little help from; + * - Alan Cox + * + * Derived from: + * - skeleton.c: A network driver outline for linux. + * Written 1993-94 by Donald Becker. + * - ltpc.c: A driver for the LocalTalk PC card. + * Written by Bradford W. Johnson. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * Changes: + * 19970608 Alan Cox Allowed dual card type support + * Can set board type in insmod + * Hooks for cops_setup routine + * (not yet implemented). + */ + +static const char *version = + "cops.c:v0.01 3/17/97 Jay Schulist \n"; +/* + * Sources: + * COPS Localtalk SDK. This provides almost all of the information + * needed. + */ + +/* + * insmod/modprobe configurable stuff. + * - IO Port, choose one your card supports or 0 if you dare. + * - IRQ, also choose one your card supports or nothing and let + * the driver figure it out. + */ + +#ifdef MODULE +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include /* For ltalk_setup() */ +#include /* For udelay() */ +#include + +#include "cops.h" /* Our Stuff */ +#include "cops_ltdrv.h" /* Firmware code for Tangent type cards. */ +#include "cops_ffdrv.h" /* Firmware code for Dayna type cards. */ + +/* + * The name of the card. Is used for messages and in the requests for + * io regions, irqs and dma channels + */ + +static const char *cardname = "cops"; + +#ifdef CONFIG_COPS_DAYNA +static int board_type = DAYNA; /* Module exported */ +#else +static int board_type = TANGENT; +#endif + +#ifdef MODULE +static int io = 0x240; /* Default IO for Dayna */ +static int irq = 5; /* Default IRQ */ +#else +static int io = 0; /* Default IO for Dayna */ +static int irq = 0; /* Default IRQ */ +#endif + +/* + * COPS Autoprobe information. + * Right now if port address is right but IRQ is not 5 this will + * return a 5 no matter what since we will still get a status response. + * Need one more additional check to narrow down after we have gotten + * the ioaddr. But since only other possible IRQs is 3 and 4 so no real + * hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with + * this driver. + * + * This driver has 2 modes and they are: Dayna mode and Tangent mode. + * Each mode corresponds with the type of card. It has been found + * that there are 2 main types of cards and all other cards are + * the same and just have different names or only have minor differences + * such as more IO ports. As this driver is tested it will + * become more clear on exactly what cards are supported. The driver + * defaults to using Dayna mode. To change the drivers mode adjust + * drivers/net/CONFIG, and the line COPS_OPTS = -DDAYNA to -DTANGENT. + * + * This driver should support: + * TANGENT driver mode: + * Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200 + * DAYNA driver mode: + * Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95, Farallon PhoneNET PC III + * Other cards possibly supported mode unkown though: + * Farallon PhoneNET PC II + * Dayna DL2000 (Full length) + * + * Cards NOT supported by this driver but supported by the ltpc.c + * driver written by Bradford W. Johnson + * Farallon PhoneNET PC + * Original Apple LocalTalk PC card + */ + +/* + * Zero terminated list of IO ports to probe. + */ + +static unsigned int cops_portlist[] = { + 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, + 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360, + 0 +}; + +/* + * Zero terminated list of IRQ ports to probe. + */ + +static int cops_irqlist[] = { + 5, 4, 3, 0 +}; + +/* use 0 for production, 1 for verification, 2 for debug, 3 for very verbose debug */ +#ifndef COPS_DEBUG +#define COPS_DEBUG 1 +#endif +static unsigned int cops_debug = COPS_DEBUG; + +/* The number of low I/O ports used by the card. */ +#define COPS_IO_EXTENT 8 + +/* Information that needs to be kept for each board. */ + +struct cops_local +{ + struct enet_statistics stats; + int board; /* Holds what board type is. */ + int nodeid; /* Set to 1 once have nodeid. */ + unsigned char node_acquire; /* Node ID when acquired. */ +}; + +/* Allocate a new device with the form of lt0, lt1, lt2, etc. */ +struct device *cops_dev_alloc(char *name) +{ + int i=0; + struct device *d=kmalloc(sizeof(struct device)+8, GFP_KERNEL); + + memset(d,0,sizeof(*d)); /* Clear the structure */ + if(d==NULL) + return NULL; + d->name=(char *)(d+1); /* Name string space */ + + /* Get next free device name */ + for(i=0;i<100;i++) + { + sprintf(d->name,name,i); + if(dev_get(d->name)==NULL) + return d; + } + return NULL; /* Over 100 of the things .. bail out! */ +} + +/* Index to functions, as function prototypes. */ +extern int cops_probe (struct device *dev); +static int cops_probe1 (struct device *dev, int ioaddr); +static int cops_irq (int ioaddr, int board); + +static int cops_open (struct device *dev); +static int cops_jumpstart (struct device *dev); +static void cops_reset (struct device *dev, int sleep); +static void cops_load (struct device *dev); +static int cops_nodeid (struct device *dev, int nodeid); + +static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs); +static void cops_rx (struct device *dev); +static int cops_send_packet (struct sk_buff *skb, struct device *dev); +static void set_multicast_list (struct device *dev); +static int cops_hard_header (struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len); + +static int cops_ioctl (struct device *dev, struct ifreq *rq, int cmd); +static int cops_close (struct device *dev); +static struct enet_statistics *cops_get_stats (struct device *dev); + + +/* + * Check for a network adaptor of this type, and return '0' iff one exists. + * If dev->base_addr == 0, probe all likely locations. + * If dev->base_addr == 1, always return failure. + * If dev->base_addr == 2, allocate space for the device and return success + * (detachable devices only). + */ +int cops_probe(struct device *dev) +{ + int i; + int base_addr = dev ? dev->base_addr : 0; + + if (base_addr == 0 && io) + base_addr=io; + + if (base_addr > 0x1ff) /* Check a single specified location. */ + return cops_probe1(dev, base_addr); + else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; + + for (i=0; cops_portlist[i]; i++) { + int ioaddr = cops_portlist[i]; + if (check_region(ioaddr, COPS_IO_EXTENT)) + continue; + if (cops_probe1(dev, ioaddr) == 0) + return 0; + } + + /* No "lt" devices found. */ + printk(KERN_WARNING "%s: No COPS localtalk devices found!\n", dev->name); + return -ENODEV; +} + +/* + * This is the real probe routine. Linux has a history of friendly device + * probes on the ISA bus. A good device probes avoids doing writes, and + * verifies that the correct device exists and functions. + */ +static int cops_probe1(struct device *dev, int ioaddr) +{ + struct cops_local *lp; + static unsigned version_printed = 0; + int irqaddr = 0; + int irqval; + + int board = board_type; + +/* Defined here to save some trouble */ + + /* Allocate a new 'dev' if needed. */ + if (dev == NULL) + { + dev=cops_dev_alloc(dev->name); /* New "lt" device; beyond lt0. */ + if(dev==NULL) + return -ENOMEM; + } + + if (cops_debug && version_printed++ == 0) + printk("%s", version); + + /* Fill in the 'dev' fields. */ + dev->base_addr = ioaddr; + + /* + * Since this board has jumpered interrupts, allocate the interrupt + * vector now. There is no point in waiting since no other device + * can use the interrupt, and this marks the irq as busy. Jumpered + * interrupts are typically not reported by the boards, and we must + * used AutoIRQ to find them. + * + */ + + if (dev->irq < 2 && irq) + dev->irq = irq; + + if (dev->irq < 2) + { + irqaddr = cops_irq(ioaddr, board); /* COPS AutoIRQ routine */ + if (irqaddr == 0) + return -EAGAIN; /* No IRQ found on this port */ + else + dev->irq = irqaddr; + } + else if (dev->irq == 2) + /* + * Fixup for users that don't know that IRQ 2 is really + * IRQ 9, or don't know which one to set. + */ + dev->irq = 9; + + /* Snarf the interrupt now. */ + irqval = request_irq(dev->irq, &cops_interrupt, 0, cardname, NULL); + if (irqval) + { + printk(KERN_WARNING "%s: Unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); + return -EAGAIN; + } + + dev->hard_start_xmit = &cops_send_packet; + + /* Initialize the device structure. */ + dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + + lp = (struct cops_local *)dev->priv; + memset(lp, 0, sizeof(struct cops_local)); + + /* Copy local board variable to lp struct. */ + lp->board = board; + + /* Tell the user where the card is and what mode were in. */ + if(board==DAYNA) + printk("%s: %s found at %#3x, using IRQ %d, in Dayna mode.\n", + dev->name, cardname, ioaddr, dev->irq); + if(board==TANGENT) + printk("%s: %s found at %#3x, using IRQ %d, in Tangent mode.\n", + dev->name, cardname, ioaddr, dev->irq); + + /* Grab the region so no one else tries to probe our ioports. */ + request_region(ioaddr, COPS_IO_EXTENT, cardname); + + /* Fill in the fields of the device structure with LocalTalk values. */ + ltalk_setup(dev); + + dev->hard_header = cops_hard_header; + dev->get_stats = cops_get_stats; + dev->open = cops_open; + dev->stop = cops_close; + dev->do_ioctl = &cops_ioctl; + dev->set_multicast_list = &set_multicast_list; + dev->mc_list = NULL; + + return 0; +} + +static int cops_irq (int ioaddr, int board) +{ /* + * This does not use the IRQ to determine where the IRQ is. We just + * assume that when we get a correct status response that is the IRQ then. + * This really just verifies the IO port but since we only have access + * to such a small number of IRQs (5, 4, 3) this is not bad. + * This will probably not work for more than one card. + */ + int irqaddr=0; + int i, x, status; + + if(board==DAYNA) + { + outb(0, ioaddr+DAYNA_RESET); + inb(ioaddr+DAYNA_RESET); + udelay(333333); + } + if(board==TANGENT) + { + inb(ioaddr); + outb(0, ioaddr); + outb(0, ioaddr+TANG_RESET); + } + + for(i=0; cops_irqlist[i] !=0; i++) + { + irqaddr = cops_irqlist[i]; + for(x = 0xFFFF; x>0; x --) /* wait for response */ + { + if(board==DAYNA) + { + status = (inb(ioaddr+DAYNA_CARD_STATUS)&3); + if (status == 1) + return irqaddr; + } + if(board==TANGENT) + { + if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0) + return irqaddr; + } + } + } + return 0; /* no IRQ found */ +} + +/* + * Open/initialize the board. This is called (in the current kernel) + * sometime after booting when the 'ifconfig' program is run. + */ +static int cops_open(struct device *dev) +{ + irq2dev_map[dev->irq] = dev; + + cops_jumpstart(dev); /* Start the card up. */ + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +/* + * This allows for a dynamic start/restart of the entire card. + */ +static int cops_jumpstart(struct device *dev) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + + /* + * Once the card has the firmware loaded and has acquired + * the nodeid, if it is reset it will lose it all. + */ + cops_reset(dev,1); /* Need to reset card before load firmware. */ + cops_load(dev); /* Load the firmware. */ + + /* + * If atalkd already gave us a nodeid we will use that + * one again, else we wait for atalkd to give us a nodeid + * in cops_ioctl. This may cause a problem if someone steals + * our nodeid while we are resetting. + */ + if(lp->nodeid == 1) + cops_nodeid(dev,lp->node_acquire); + + return 0; +} + +static int tangent_wait_reset(int ioaddr) +{ + int timeout=0; + + while(timeout < 5000 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) + udelay(1000); /* Wait 1000 useconds */ + + return 0; +} + +/* + * Reset the LocalTalk board. + */ +static void cops_reset(struct device *dev, int sleep) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + int ioaddr=dev->base_addr; + + if(lp->board==TANGENT) + { + inb(ioaddr); /* Clear request latch. */ + outb(0,ioaddr); /* Clear the TANG_TX_READY flop. */ + outb(0, ioaddr+TANG_RESET); /* Reset the adapter. */ + + /* Can take 5 seconds max - youch! */ + if(sleep) + { + long snapt=jiffies; + while(jiffies-snapt<5*HZ) + { + if(inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY) + break; + schedule(); + } + } + else + tangent_wait_reset(ioaddr); + outb(0, ioaddr+TANG_CLEAR_INT); + } + if(lp->board==DAYNA) + { + outb(0, ioaddr+DAYNA_RESET); /* Assert the reset port */ + inb(ioaddr+DAYNA_RESET); /* Clear the reset */ + if(sleep) + { + long snap=jiffies; + + /* Let card finish initializing, about 1/3 second */ + while(jiffies-snaptbusy=0; + + return; +} + +static void cops_load (struct device *dev) +{ + struct ifreq ifr; + struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_data; + struct cops_local *lp=(struct cops_local *)dev->priv; + int ioaddr=dev->base_addr; + int length, i = 0; + + strcpy(ifr.ifr_name,"lt0"); + + /* Get card's firmware code and do some checks on it. */ +#ifdef CONFIG_COPS_DAYNA + if (lp->board==DAYNA) + { + ltf->length=sizeof(ffdrv_code); + ltf->data=ffdrv_code; + } + else +#endif +#ifdef CONFIG_COPS_TANGENT + if (lp->board==TANGENT) + { + ltf->length=sizeof(ltdrv_code); + ltf->data=ltdrv_code; + } + else +#endif + { + printk(KERN_INFO "%s; unsupported board type.\n", dev->name); + return; + } + + /* Check to make sure firmware is correct length. */ + if(lp->board==DAYNA && ltf->length!=5983) + { + printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name); + return; + } + if(lp->board==TANGENT && ltf->length!=2501) + { + printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name); + return; + } + + if(lp->board==DAYNA) + { + /* + * We must wait for a status response + * with the DAYNA board. + */ + while(++i<65536) + { + if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1) + break; + } + + if(i==65536) + return; + } + + /* + * Upload the firmware and kick. Byte-by-byte works nicely here. + */ + i=0; + length = ltf->length; + while(length--) + { + outb(ltf->data[i], ioaddr); + i++; + } + + if(cops_debug > 1) + printk(KERN_DEBUG "%s: Uploaded firmware - %d bytes of %d bytes.\n", dev->name, i, ltf->length); + + if(lp->board==DAYNA) + outb(1, ioaddr+DAYNA_INT_CARD); /* Tell Dayna to run the firmware code. */ + else + inb(ioaddr); /* Tell Tang to run the firmware code. */ + + if(lp->board==TANGENT) + { + tangent_wait_reset(ioaddr); + inb(ioaddr); /* Clear initial ready signal. */ + } + + return; +} + +/* + * Get the LocalTalk Nodeid from the card. We can suggest + * any nodeid 1-254. The card will try and get that exact + * address else we can specify 0 as the nodeid and the card + * will autoprobe for a nodeid. + */ +static int cops_nodeid (struct device *dev, int nodeid) +{ + struct cops_local *lp = (struct cops_local *) dev->priv; + int ioaddr = dev->base_addr; + + if (lp->board == DAYNA) + { + /* Empty any pending adapter responses. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0) + { + outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ + if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) + cops_rx(dev); /* Kick out any packet waiting. */ + schedule(); + } + + outb(2, ioaddr); /* Output command packet length as 2. */ + outb(0, ioaddr); + outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ + outb(nodeid, ioaddr); /* Suggest node address. */ + } + + if (lp->board == TANGENT) + { + /* Empty any pending adapter responses. */ + while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) + { + outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ + cops_rx(dev); /* Kick out any packet waiting. */ + schedule(); + } + + /* Not sure what Tangent does if random nodeid we picked is already used. */ + if(nodeid == 0) /* Seed. */ + nodeid = jiffies&0xFF; /* Get a random try .*/ + outb(2, ioaddr); /* Command length LSB. */ + outb(0, ioaddr); /* Command length MSB. */ + outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ + outb(nodeid, ioaddr); /* LAP address hint. */ + outb(0xFF, ioaddr); /* Interrupt level to use (NONE). */ + } + + lp->node_acquire=0; /* Set nodeid holder to 0. */ + while(lp->node_acquire==0) /* Get *True* nodeid finally. */ + { + outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ + + if(lp->board == DAYNA) + { + if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) + cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ + } + if(lp->board == TANGENT) + { + if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) + cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ + } + schedule(); + } + + if(cops_debug > 1) + printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", dev->name, lp->node_acquire); + + lp->nodeid=1; /* Set got nodeid to 1. */ + + return 0; +} + +/* + * The typical workload of the driver: + * Handle the network interface interrupts. + */ +static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct device *dev = (struct device *) irq2dev_map[irq]; + struct cops_local *lp; + int ioaddr, status; + int boguscount = 0; + + if (dev == NULL) + { + printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq); + return; + } + dev->interrupt = 1; + + ioaddr = dev->base_addr; + lp = (struct cops_local *)dev->priv; + + do + { + /* Clear any interrupt. */ + outb(0, ioaddr + COPS_CLEAR_INT); + + if(lp->board==DAYNA) + { + status=inb(ioaddr+DAYNA_CARD_STATUS); + if((status&0x03)==DAYNA_RX_REQUEST) + cops_rx(dev); + } + else + { + status=inb(ioaddr+TANG_CARD_STATUS); + if (status&TANG_RX_READY) + cops_rx(dev); + } + + dev->tbusy = 0; + mark_bh(NET_BH); + } while (++boguscount < 20 ); + dev->interrupt = 0; + + return; +} + +/* + * We have a good packet(s), get it/them out of the buffers. + */ +static void cops_rx(struct device *dev) +{ + int pkt_len = 0; + int rsp_type = 0; + struct sk_buff *skb; + struct cops_local *lp = (struct cops_local *)dev->priv; + int ioaddr = dev->base_addr; + int boguscount = 0; + + cli(); /* Disable interrupts. */ + + if(lp->board==DAYNA) + { + outb(0, ioaddr); /* Send out Zero length. */ + outb(0, ioaddr); + outb(DATA_READ, ioaddr); /* Send read command out. */ + + /* Wait for DMA to turn around. */ + while(++boguscount<1000000) + { + if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY) + break; + } + + if(boguscount==1000000) + { + printk(KERN_WARNING "%s: DMA timed out.\n",dev->name); + return; + } + } + + /* Get response length. */ + pkt_len = inb(ioaddr) & 0xFF; + pkt_len |= (inb(ioaddr) << 8); + /* Input IO code. */ + rsp_type=inb(ioaddr); + + /* Malloc up new buffer. */ + skb = dev_alloc_skb(pkt_len); + if (skb == NULL) + { + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + lp->stats.rx_dropped++; + while(pkt_len--) /* Discard packet */ + inb(ioaddr); + return; + } + skb->dev = dev; + skb_put(skb, pkt_len); + skb->protocol = htons(ETH_P_LOCALTALK); + + insb(ioaddr, skb->data, pkt_len); /* Eat the Data */ + + if(lp->board==DAYNA) + outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card. */ + + sti(); /* Restore interrupts. */ + + /* Check for bad response length */ + if (pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) + { + printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len); + lp->stats.tx_errors++; + kfree_skb(skb, FREE_READ); + return; + } + + /* Set nodeid and then get out. */ + if(rsp_type == LAP_INIT_RSP) + { + lp->node_acquire = skb->data[0]; /* Nodeid taken from received packet. */ + kfree_skb(skb, FREE_READ); + return; + } + + /* One last check to make sure we have a good packet. */ + if(rsp_type != LAP_RESPONSE) + { + printk("%s: Bad packet type %d.\n", dev->name, rsp_type); + lp->stats.tx_errors++; + kfree_skb(skb, FREE_READ); + return; + } + + skb->mac.raw = skb->data; /* Point to entire packet. */ + skb_pull(skb,3); + skb->h.raw = skb->data; /* Point to just the data (Skip header). */ + + /* Update the counters. */ + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + + /* Send packet to a higher place. */ + netif_rx(skb); + + return; +} + +/* + * Make the card transmit a LocalTalk packet. + */ +static int cops_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + int ioaddr = dev->base_addr; + + if (dev->tbusy) + { + /* + * If we get here, some higher level has decided we are broken. + * There should really be a "kick me" function call instead. + */ + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5) + return 1; + lp->stats.tx_errors++; + if(lp->board==TANGENT) + { + if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) + printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); + } + printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); + cops_jumpstart(dev); /* Restart the card. */ + dev->tbusy=0; + dev->trans_start = jiffies; + } + + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ + if (test_and_set_bit(0, (void*) &dev->tbusy) != 0) + printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); + else + { + cli(); /* Disable interrupts. */ + if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0); + + /* Output IO length. */ + if(lp->board == DAYNA) + { + outb(skb->len, ioaddr); + outb(skb->len >> 8, ioaddr); + } + else + { + outb(skb->len&0x0FF, ioaddr); + outb((skb->len >> 8)&0x0FF, ioaddr); + } + + /* Output IO code. */ + outb(LAP_WRITE, ioaddr); + + if(lp->board == DAYNA) /* Check the transmit buffer again. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + + outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ + + if(lp->board==DAYNA) /* The Dayna requires you kick the card. */ + outb(1, ioaddr+DAYNA_INT_CARD); + + sti(); /* Restore interrupts. */ + + /* Done sending packet, update counters and cleanup. */ + lp->stats.tx_packets++; + lp->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + } + + dev_kfree_skb (skb, FREE_WRITE); + dev->tbusy = 0; + + return 0; +} + +/* + * Dummy function to keep the Appletalk layer happy. + */ + +static void set_multicast_list(struct device *dev) +{ + if(cops_debug >= 3) + printk("%s: set_mulicast_list executed. NeatO.\n", dev->name); +} + +/* + * Another Dummy function to keep the Appletalk layer happy. + */ + +static int cops_hard_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) +{ + if(cops_debug >= 3) + printk("%s: cops_hard_header executed. Wow!\n", dev->name); + return 0; +} + +/* + * System ioctls for the COPS LocalTalk card. + */ + +static int cops_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + struct sockaddr_at *sa=(struct sockaddr_at *)&ifr->ifr_addr; + struct at_addr *aa=(struct at_addr *)&dev->pa_addr; + + switch(cmd) + { + case SIOCSIFADDR: + /* Get and set the nodeid and network # atalkd wants. */ + cops_nodeid(dev, sa->sat_addr.s_node); + aa->s_net = sa->sat_addr.s_net; + aa->s_node = lp->node_acquire; + + /* Set broardcast address. */ + dev->broadcast[0] = 0xFF; + + /* Set hardware address. */ + dev->dev_addr[0] = aa->s_node; + dev->addr_len = 1; + return 0; + + case SIOCGIFADDR: + sa->sat_addr.s_net = aa->s_net; + sa->sat_addr.s_node = aa->s_node; + return 0; + + default: + return -EOPNOTSUPP; + } +} + +/* + * The inverse routine to cops_open(). + */ + +static int cops_close(struct device *dev) +{ + dev->tbusy = 1; + dev->start = 0; + irq2dev_map[dev->irq] = 0; + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct enet_statistics *cops_get_stats(struct device *dev) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + return &lp->stats; +} + +#ifdef MODULE +static struct device dev_cops = +{ + "lt0", /* device name */ + 0, 0, 0, 0, + 0x0, 0, /* I/O address, IRQ */ + 0, 0, 0, NULL, cops_probe +}; + + +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(board_type, "i"); + +int init_module(void) +{ + int result; + + if (io == 0) + printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", cardname); + + /* Copy the parameters from insmod into the device structure. */ + dev_cops.base_addr = io; + dev_cops.irq = irq; + + if ((result = register_netdev(&dev_cops)) != 0) + return result; + + return 0; +} + +void cleanup_module(void) +{ + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + + free_irq(dev_cops.irq, NULL); + release_region(dev_cops.base_addr, COPS_IO_EXTENT); + unregister_netdev(&dev_cops); + + if (dev_cops.priv) + kfree_s(dev_cops.priv, sizeof(struct cops_local)); +} +#endif /* MODULE */ diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops.h linux/drivers/net/cops.h --- v2.1.43/linux/drivers/net/cops.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/cops.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,60 @@ +/* cops.h: LocalTalk driver for Linux. + * + * Authors: + * - Jay Schulist + */ + +#ifndef __LINUX_COPSLTALK_H +#define __LINUX_COPSLTALK_H + +#ifdef __KERNEL__ + +/* Max LLAP size we will accept. */ +#define MAX_LLAP_SIZE 603 + +/* Tangent */ +#define TANG_CARD_STATUS 1 +#define TANG_CLEAR_INT 1 +#define TANG_RESET 3 + +#define TANG_TX_READY 1 +#define TANG_RX_READY 2 + +/* Dayna */ +#define DAYNA_CMD_DATA 0 +#define DAYNA_CLEAR_INT 1 +#define DAYNA_CARD_STATUS 2 +#define DAYNA_INT_CARD 3 +#define DAYNA_RESET 4 + +#define DAYNA_RX_READY 0 +#define DAYNA_TX_READY 1 +#define DAYNA_RX_REQUEST 3 + +/* Same on both card types */ +#define COPS_CLEAR_INT 1 + +/* LAP response codes recieved from the cards. */ +#define LAP_INIT 1 /* Init cmd */ +#define LAP_INIT_RSP 2 /* Init response */ +#define LAP_WRITE 3 /* Write cmd */ +#define DATA_READ 4 /* Data read */ +#define LAP_RESPONSE 4 /* Received ALAP frame response */ +#define LAP_GETSTAT 5 /* Get LAP and HW status */ +#define LAP_RSPSTAT 6 /* Status response */ + +#endif + +/* + * Structure to hold the firmware information. + */ +struct ltfirmware +{ + unsigned int length; + unsigned char * data; +}; + +#define DAYNA 1 +#define TANGENT 2 + +#endif diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops_ffdrv.h linux/drivers/net/cops_ffdrv.h --- v2.1.43/linux/drivers/net/cops_ffdrv.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/cops_ffdrv.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,532 @@ + +/* + * The firmware this driver downloads into the Localtalk card is a + * seperate program and is not GPL'd source code, even though the Linux + * side driver and the routine that loads this data into the card are. + * + * It is taken from the COPS SDK and is under the following license + * + * This material is licensed to you strictly for use in conjunction with + * the use of COPS LocalTalk adapters. + * There is no charge for this SDK. And no waranty express or implied + * about its fitness for any purpose. However, we will cheerefully + * refund every penny you paid for this SDK... + * Regards, + * + * Thomas F. Divine + * Chief Scientist + */ + + +/* cops_ffdrv.h: LocalTalk driver firmware dump for Linux. + * + * Authors: + * - Jay Schulist + */ + + +#ifdef CONFIG_COPS_DAYNA + +unsigned char ffdrv_code[] = { + 58,3,0,50,228,149,33,255,255,34,226,149, + 249,17,40,152,33,202,154,183,237,82,77,68, + 11,107,98,19,54,0,237,176,175,50,80,0, + 62,128,237,71,62,32,237,57,51,62,12,237, + 57,50,237,57,54,62,6,237,57,52,62,12, + 237,57,49,33,107,137,34,32,128,33,83,130, + 34,40,128,33,86,130,34,42,128,33,112,130, + 34,36,128,33,211,130,34,38,128,62,0,237, + 57,16,33,63,148,34,34,128,237,94,205,15, + 130,251,205,168,145,24,141,67,111,112,121,114, + 105,103,104,116,32,40,67,41,32,49,57,56, + 56,32,45,32,68,97,121,110,97,32,67,111, + 109,109,117,110,105,99,97,116,105,111,110,115, + 32,32,32,65,108,108,32,114,105,103,104,116, + 115,32,114,101,115,101,114,118,101,100,46,32, + 32,40,68,40,68,7,16,8,34,7,22,6, + 16,5,12,4,8,3,6,140,0,16,39,128, + 0,4,96,10,224,6,0,7,126,2,64,11, + 118,12,6,13,0,14,193,15,0,5,96,3, + 192,1,64,9,8,62,9,211,66,62,192,211, + 66,62,100,61,32,253,6,28,33,205,129,14, + 66,237,163,194,253,129,6,28,33,205,129,14, + 64,237,163,194,9,130,201,62,47,50,71,152, + 62,47,211,68,58,203,129,237,57,20,58,204, + 129,237,57,21,33,77,152,54,132,205,233,129, + 58,228,149,254,209,40,6,56,4,62,0,24, + 2,219,96,33,233,149,119,230,62,33,232,149, + 119,213,33,8,152,17,7,0,25,119,19,25, + 119,209,201,251,237,77,245,197,213,229,221,229, + 205,233,129,62,1,50,106,137,205,158,139,221, + 225,225,209,193,241,251,237,77,245,197,213,219, + 72,237,56,16,230,46,237,57,16,237,56,12, + 58,72,152,183,32,26,6,20,17,128,2,237, + 56,46,187,32,35,237,56,47,186,32,29,219, + 72,230,1,32,3,5,32,232,175,50,72,152, + 229,221,229,62,1,50,106,137,205,158,139,221, + 225,225,24,25,62,1,50,72,152,58,201,129, + 237,57,12,58,202,129,237,57,13,237,56,16, + 246,17,237,57,16,209,193,241,251,237,77,245, + 197,229,213,221,229,237,56,16,230,17,237,57, + 16,237,56,20,58,34,152,246,16,246,8,211, + 68,62,6,61,32,253,58,34,152,246,8,211, + 68,58,203,129,237,57,20,58,204,129,237,57, + 21,237,56,16,246,34,237,57,16,221,225,209, + 225,193,241,251,237,77,33,2,0,57,126,230, + 3,237,100,1,40,2,246,128,230,130,245,62, + 5,211,64,241,211,64,201,229,213,243,237,56, + 16,230,46,237,57,16,237,56,12,251,70,35, + 35,126,254,175,202,77,133,254,129,202,15,133, + 230,128,194,191,132,43,58,44,152,119,33,76, + 152,119,35,62,132,119,120,254,255,40,4,58, + 49,152,119,219,72,43,43,112,17,3,0,237, + 56,52,230,248,237,57,52,219,72,230,1,194, + 141,131,209,225,237,56,52,246,6,237,57,52, + 62,1,55,251,201,62,3,211,66,62,192,211, + 66,62,48,211,66,0,0,219,66,230,1,40, + 4,219,67,24,240,205,203,135,58,75,152,254, + 255,202,128,132,58,49,152,254,161,250,207,131, + 58,34,152,211,68,62,10,211,66,62,128,211, + 66,62,11,211,66,62,6,211,66,24,0,62, + 14,211,66,62,33,211,66,62,1,211,66,62, + 64,211,66,62,3,211,66,62,209,211,66,62, + 100,71,219,66,230,1,32,6,5,32,247,195, + 248,132,219,67,71,58,44,152,184,194,248,132, + 62,100,71,219,66,230,1,32,6,5,32,247, + 195,248,132,219,67,62,100,71,219,66,230,1, + 32,6,5,32,247,195,248,132,219,67,254,133, + 32,7,62,0,50,74,152,24,17,254,173,32, + 7,62,1,50,74,152,24,6,254,141,194,248, + 132,71,209,225,58,49,152,254,132,32,10,62, + 50,205,2,134,205,144,135,24,27,254,140,32, + 15,62,110,205,2,134,62,141,184,32,5,205, + 144,135,24,8,62,10,205,2,134,205,8,134, + 62,1,50,106,137,205,158,139,237,56,52,246, + 6,237,57,52,175,183,251,201,62,20,135,237, + 57,20,175,237,57,21,237,56,16,246,2,237, + 57,16,237,56,20,95,237,56,21,123,254,10, + 48,244,237,56,16,230,17,237,57,16,209,225, + 205,144,135,62,1,50,106,137,205,158,139,237, + 56,52,246,6,237,57,52,175,183,251,201,209, + 225,243,219,72,230,1,40,13,62,10,211,66, + 0,0,219,66,230,192,202,226,132,237,56,52, + 246,6,237,57,52,62,1,55,251,201,205,203, + 135,62,1,50,106,137,205,158,139,237,56,52, + 246,6,237,57,52,183,251,201,209,225,62,1, + 50,106,137,205,158,139,237,56,52,246,6,237, + 57,52,62,2,55,251,201,209,225,243,219,72, + 230,1,202,213,132,62,10,211,66,0,0,219, + 66,230,192,194,213,132,229,62,1,50,106,137, + 42,40,152,205,65,143,225,17,3,0,205,111, + 136,62,6,211,66,58,44,152,211,66,237,56, + 52,246,6,237,57,52,183,251,201,209,197,237, + 56,52,230,248,237,57,52,219,72,230,1,32, + 15,193,225,237,56,52,246,6,237,57,52,62, + 1,55,251,201,14,23,58,37,152,254,0,40, + 14,14,2,254,1,32,5,62,140,119,24,3, + 62,132,119,43,43,197,205,203,135,193,62,1, + 211,66,62,64,211,66,62,3,211,66,62,193, + 211,66,62,100,203,39,71,219,66,230,1,32, + 6,5,32,247,195,229,133,33,238,151,219,67, + 71,58,44,152,184,194,229,133,119,62,100,71, + 219,66,230,1,32,6,5,32,247,195,229,133, + 219,67,35,119,13,32,234,193,225,62,1,50, + 106,137,205,158,139,237,56,52,246,6,237,57, + 52,175,183,251,201,33,234,151,35,35,62,255, + 119,193,225,62,1,50,106,137,205,158,139,237, + 56,52,246,6,237,57,52,175,251,201,243,61, + 32,253,251,201,62,3,211,66,62,192,211,66, + 58,49,152,254,140,32,19,197,229,213,17,181, + 129,33,185,129,1,2,0,237,176,209,225,193, + 24,27,229,213,33,187,129,58,49,152,230,15, + 87,30,2,237,92,25,17,181,129,126,18,19, + 35,126,18,209,225,58,34,152,246,8,211,68, + 58,49,152,254,165,40,14,254,164,40,10,62, + 10,211,66,62,224,211,66,24,25,58,74,152, + 254,0,40,10,62,10,211,66,62,160,211,66, + 24,8,62,10,211,66,62,128,211,66,62,11, + 211,66,62,6,211,66,205,147,143,62,5,211, + 66,62,224,211,66,62,5,211,66,62,96,211, + 66,62,5,61,32,253,62,5,211,66,62,224, + 211,66,62,14,61,32,253,62,5,211,66,62, + 233,211,66,62,128,211,66,58,181,129,61,32, + 253,62,1,211,66,62,192,211,66,1,254,19, + 237,56,46,187,32,6,13,32,247,195,226,134, + 62,192,211,66,0,0,219,66,203,119,40,250, + 219,66,203,87,40,250,243,237,56,16,230,17, + 237,57,16,237,56,20,251,62,5,211,66,62, + 224,211,66,58,182,129,61,32,253,229,33,181, + 129,58,183,129,203,63,119,35,58,184,129,119, + 225,62,10,211,66,62,224,211,66,62,11,211, + 66,62,118,211,66,62,47,211,68,62,5,211, + 66,62,233,211,66,58,181,129,61,32,253,62, + 5,211,66,62,224,211,66,58,182,129,61,32, + 253,62,5,211,66,62,96,211,66,201,229,213, + 58,50,152,230,15,87,30,2,237,92,33,187, + 129,25,17,181,129,126,18,35,19,126,18,209, + 225,58,71,152,246,8,211,68,58,50,152,254, + 165,40,14,254,164,40,10,62,10,211,66,62, + 224,211,66,24,8,62,10,211,66,62,128,211, + 66,62,11,211,66,62,6,211,66,195,248,135, + 62,3,211,66,62,192,211,66,197,229,213,17, + 181,129,33,183,129,1,2,0,237,176,209,225, + 193,62,47,211,68,62,10,211,66,62,224,211, + 66,62,11,211,66,62,118,211,66,62,1,211, + 66,62,0,211,66,205,147,143,195,16,136,62, + 3,211,66,62,192,211,66,197,229,213,17,181, + 129,33,183,129,1,2,0,237,176,209,225,193, + 62,47,211,68,62,10,211,66,62,224,211,66, + 62,11,211,66,62,118,211,66,205,147,143,62, + 5,211,66,62,224,211,66,62,5,211,66,62, + 96,211,66,62,5,61,32,253,62,5,211,66, + 62,224,211,66,62,14,61,32,253,62,5,211, + 66,62,233,211,66,62,128,211,66,58,181,129, + 61,32,253,62,1,211,66,62,192,211,66,1, + 254,19,237,56,46,187,32,6,13,32,247,195, + 88,136,62,192,211,66,0,0,219,66,203,119, + 40,250,219,66,203,87,40,250,62,5,211,66, + 62,224,211,66,58,182,129,61,32,253,62,5, + 211,66,62,96,211,66,201,197,14,67,6,0, + 62,3,211,66,62,192,211,66,62,48,211,66, + 0,0,219,66,230,1,40,4,219,67,24,240, + 62,5,211,66,62,233,211,66,62,128,211,66, + 58,181,129,61,32,253,237,163,29,62,192,211, + 66,219,66,230,4,40,250,237,163,29,32,245, + 219,66,230,4,40,250,62,255,71,219,66,230, + 4,40,3,5,32,247,219,66,230,4,40,250, + 62,5,211,66,62,224,211,66,58,182,129,61, + 32,253,62,5,211,66,62,96,211,66,58,71, + 152,254,1,202,18,137,62,16,211,66,62,56, + 211,66,62,14,211,66,62,33,211,66,62,1, + 211,66,62,248,211,66,237,56,48,246,153,230, + 207,237,57,48,62,3,211,66,62,221,211,66, + 193,201,58,71,152,211,68,62,10,211,66,62, + 128,211,66,62,11,211,66,62,6,211,66,62, + 6,211,66,58,44,152,211,66,62,16,211,66, + 62,56,211,66,62,48,211,66,0,0,62,14, + 211,66,62,33,211,66,62,1,211,66,62,248, + 211,66,237,56,48,246,145,246,8,230,207,237, + 57,48,62,3,211,66,62,221,211,66,193,201, + 44,3,1,0,70,69,1,245,197,213,229,175, + 50,72,152,237,56,16,230,46,237,57,16,237, + 56,12,62,1,211,66,0,0,219,66,95,230, + 160,32,3,195,20,139,123,230,96,194,72,139, + 62,48,211,66,62,1,211,66,62,64,211,66, + 237,91,40,152,205,207,143,25,43,55,237,82, + 218,70,139,34,42,152,98,107,58,44,152,190, + 194,210,138,35,35,62,130,190,194,200,137,62, + 1,50,48,152,62,175,190,202,82,139,62,132, + 190,32,44,50,50,152,62,47,50,71,152,229, + 175,50,106,137,42,40,152,205,65,143,225,54, + 133,43,70,58,44,152,119,43,112,17,3,0, + 62,10,205,2,134,205,111,136,195,158,138,62, + 140,190,32,19,50,50,152,58,233,149,230,4, + 202,222,138,62,1,50,71,152,195,219,137,126, + 254,160,250,185,138,254,166,242,185,138,50,50, + 152,43,126,35,229,213,33,234,149,95,22,0, + 25,126,254,132,40,18,254,140,40,14,58,50, + 152,230,15,87,126,31,21,242,65,138,56,2, + 175,119,58,50,152,230,15,87,58,233,149,230, + 62,31,21,242,85,138,218,98,138,209,225,195, + 20,139,58,50,152,33,100,137,230,15,95,22, + 0,25,126,50,71,152,209,225,58,50,152,254, + 164,250,135,138,58,73,152,254,0,40,4,54, + 173,24,2,54,133,43,70,58,44,152,119,43, + 112,17,3,0,205,70,135,175,50,106,137,205, + 208,139,58,199,129,237,57,12,58,200,129,237, + 57,13,237,56,16,246,17,237,57,16,225,209, + 193,241,251,237,77,62,129,190,194,227,138,54, + 130,43,70,58,44,152,119,43,112,17,3,0, + 205,144,135,195,20,139,35,35,126,254,132,194, + 227,138,175,50,106,137,205,158,139,24,42,58, + 201,154,254,1,40,7,62,1,50,106,137,24, + 237,58,106,137,254,1,202,222,138,62,128,166, + 194,222,138,221,229,221,33,67,152,205,127,142, + 205,109,144,221,225,225,209,193,241,251,237,77, + 58,106,137,254,1,202,44,139,58,50,152,254, + 164,250,44,139,58,73,152,238,1,50,73,152, + 221,229,221,33,51,152,205,127,142,221,225,62, + 1,50,106,137,205,158,139,195,13,139,24,208, + 24,206,24,204,230,64,40,3,195,20,139,195, + 20,139,43,126,33,8,152,119,35,58,44,152, + 119,43,237,91,35,152,205,203,135,205,158,139, + 195,13,139,175,50,78,152,62,3,211,66,62, + 192,211,66,201,197,33,4,0,57,126,35,102, + 111,62,1,50,106,137,219,72,205,141,139,193, + 201,62,1,50,78,152,34,40,152,54,0,35, + 35,54,0,195,163,139,58,78,152,183,200,229, + 33,181,129,58,183,129,119,35,58,184,129,119, + 225,62,47,211,68,62,14,211,66,62,193,211, + 66,62,10,211,66,62,224,211,66,62,11,211, + 66,62,118,211,66,195,3,140,58,78,152,183, + 200,58,71,152,211,68,254,69,40,4,254,70, + 32,17,58,73,152,254,0,40,10,62,10,211, + 66,62,160,211,66,24,8,62,10,211,66,62, + 128,211,66,62,11,211,66,62,6,211,66,62, + 6,211,66,58,44,152,211,66,62,16,211,66, + 62,56,211,66,62,48,211,66,0,0,219,66, + 230,1,40,4,219,67,24,240,62,14,211,66, + 62,33,211,66,42,40,152,205,65,143,62,1, + 211,66,62,248,211,66,237,56,48,246,145,246, + 8,230,207,237,57,48,62,3,211,66,62,221, + 211,66,201,62,16,211,66,62,56,211,66,62, + 48,211,66,0,0,219,66,230,1,40,4,219, + 67,24,240,62,14,211,66,62,33,211,66,62, + 1,211,66,62,248,211,66,237,56,48,246,153, + 230,207,237,57,48,62,3,211,66,62,221,211, + 66,201,229,213,33,234,149,95,22,0,25,126, + 254,132,40,4,254,140,32,2,175,119,123,209, + 225,201,6,8,14,0,31,48,1,12,16,250, + 121,201,33,4,0,57,94,35,86,33,2,0, + 57,126,35,102,111,221,229,34,89,152,237,83, + 91,152,221,33,63,152,205,127,142,58,81,152, + 50,82,152,58,80,152,135,50,80,152,205,162, + 140,254,3,56,16,58,81,152,135,60,230,15, + 50,81,152,175,50,80,152,24,23,58,79,152, + 205,162,140,254,3,48,13,58,81,152,203,63, + 50,81,152,62,255,50,79,152,58,81,152,50, + 82,152,58,79,152,135,50,79,152,62,32,50, + 83,152,50,84,152,237,56,16,230,17,237,57, + 16,219,72,62,192,50,93,152,62,93,50,94, + 152,58,93,152,61,50,93,152,32,9,58,94, + 152,61,50,94,152,40,44,62,170,237,57,20, + 175,237,57,21,237,56,16,246,2,237,57,16, + 219,72,230,1,202,29,141,237,56,20,71,237, + 56,21,120,254,10,48,237,237,56,16,230,17, + 237,57,16,243,62,14,211,66,62,65,211,66, + 251,58,39,152,23,23,60,50,39,152,71,58, + 82,152,160,230,15,40,22,71,14,10,219,66, + 230,16,202,186,141,219,72,230,1,202,186,141, + 13,32,239,16,235,42,89,152,237,91,91,152, + 205,47,131,48,7,61,202,186,141,195,227,141, + 221,225,33,0,0,201,221,33,55,152,205,127, + 142,58,84,152,61,50,84,152,40,19,58,82, + 152,246,1,50,82,152,58,79,152,246,1,50, + 79,152,195,29,141,221,225,33,1,0,201,221, + 33,59,152,205,127,142,58,80,152,246,1,50, + 80,152,58,82,152,135,246,1,50,82,152,58, + 83,152,61,50,83,152,194,29,141,221,225,33, + 2,0,201,221,229,33,0,0,57,17,4,0, + 25,126,50,44,152,230,128,50,85,152,58,85, + 152,183,40,6,221,33,88,2,24,4,221,33, + 150,0,58,44,152,183,40,53,60,40,50,60, + 40,47,61,61,33,86,152,119,35,119,35,54, + 129,175,50,48,152,221,43,221,229,225,124,181, + 40,42,33,86,152,17,3,0,205,189,140,17, + 232,3,27,123,178,32,251,58,48,152,183,40, + 224,58,44,152,71,62,7,128,230,127,71,58, + 85,152,176,50,44,152,24,162,221,225,201,183, + 221,52,0,192,221,52,1,192,221,52,2,192, + 221,52,3,192,55,201,245,62,1,211,100,241, + 201,245,62,1,211,96,241,201,33,2,0,57, + 126,35,102,111,237,56,48,230,175,237,57,48, + 62,48,237,57,49,125,237,57,32,124,237,57, + 33,62,0,237,57,34,62,88,237,57,35,62, + 0,237,57,36,237,57,37,33,128,2,125,237, + 57,38,124,237,57,39,237,56,48,246,97,230, + 207,237,57,48,62,0,237,57,0,62,0,211, + 96,211,100,201,33,2,0,57,126,35,102,111, + 237,56,48,230,175,237,57,48,62,12,237,57, + 49,62,76,237,57,32,62,0,237,57,33,237, + 57,34,125,237,57,35,124,237,57,36,62,0, + 237,57,37,33,128,2,125,237,57,38,124,237, + 57,39,237,56,48,246,97,230,207,237,57,48, + 62,1,211,96,201,33,2,0,57,126,35,102, + 111,229,237,56,48,230,87,237,57,48,125,237, + 57,40,124,237,57,41,62,0,237,57,42,62, + 67,237,57,43,62,0,237,57,44,58,106,137, + 254,1,32,5,33,6,0,24,3,33,128,2, + 125,237,57,46,124,237,57,47,237,56,50,230, + 252,246,2,237,57,50,225,201,33,4,0,57, + 94,35,86,33,2,0,57,126,35,102,111,237, + 56,48,230,87,237,57,48,125,237,57,40,124, + 237,57,41,62,0,237,57,42,62,67,237,57, + 43,62,0,237,57,44,123,237,57,46,122,237, + 57,47,237,56,50,230,244,246,0,237,57,50, + 237,56,48,246,145,230,207,237,57,48,201,213, + 237,56,46,95,237,56,47,87,237,56,46,111, + 237,56,47,103,183,237,82,32,235,33,128,2, + 183,237,82,209,201,213,237,56,38,95,237,56, + 39,87,237,56,38,111,237,56,39,103,183,237, + 82,32,235,33,128,2,183,237,82,209,201,245, + 197,1,52,0,237,120,230,253,237,121,193,241, + 201,245,197,1,52,0,237,120,246,2,237,121, + 193,241,201,33,2,0,57,126,35,102,111,126, + 35,110,103,201,33,0,0,34,102,152,34,96, + 152,34,98,152,33,202,154,34,104,152,237,91, + 104,152,42,226,149,183,237,82,17,0,255,25, + 34,100,152,203,124,40,6,33,0,125,34,100, + 152,42,104,152,35,35,35,229,205,120,139,193, + 201,205,186,149,229,42,40,152,35,35,35,229, + 205,39,144,193,124,230,3,103,221,117,254,221, + 116,255,237,91,42,152,35,35,35,183,237,82, + 32,12,17,5,0,42,42,152,205,171,149,242, + 169,144,42,40,152,229,205,120,139,193,195,198, + 149,237,91,42,152,42,98,152,25,34,98,152, + 19,19,19,42,102,152,25,34,102,152,237,91, + 100,152,33,158,253,25,237,91,102,152,205,171, + 149,242,214,144,33,0,0,34,102,152,62,1, + 50,95,152,205,225,144,195,198,149,58,95,152, + 183,200,237,91,96,152,42,102,152,205,171,149, + 242,5,145,237,91,102,152,33,98,2,25,237, + 91,96,152,205,171,149,250,37,145,237,91,96, + 152,42,102,152,183,237,82,32,7,42,98,152, + 125,180,40,13,237,91,102,152,42,96,152,205, + 171,149,242,58,145,237,91,104,152,42,102,152, + 25,35,35,35,229,205,120,139,193,175,50,95, + 152,201,195,107,139,205,206,149,250,255,243,205, + 225,144,251,58,230,149,183,194,198,149,17,1, + 0,42,98,152,205,171,149,250,198,149,62,1, + 50,230,149,237,91,96,152,42,104,152,25,221, + 117,252,221,116,253,237,91,104,152,42,96,152, + 25,35,35,35,221,117,254,221,116,255,35,35, + 35,229,205,39,144,124,230,3,103,35,35,35, + 221,117,250,221,116,251,235,221,110,252,221,102, + 253,115,35,114,35,54,4,62,1,211,100,211, + 84,195,198,149,33,0,0,34,102,152,34,96, + 152,34,98,152,33,202,154,34,104,152,237,91, + 104,152,42,226,149,183,237,82,17,0,255,25, + 34,100,152,33,109,152,54,0,33,107,152,229, + 205,240,142,193,62,47,50,34,152,62,132,50, + 49,152,205,241,145,205,61,145,58,39,152,60, + 50,39,152,24,241,205,206,149,251,255,33,109, + 152,126,183,202,198,149,110,221,117,251,33,109, + 152,54,0,221,126,251,254,1,40,28,254,3, + 40,101,254,4,202,190,147,254,5,202,147,147, + 254,8,40,87,33,107,152,229,205,240,142,195, + 198,149,58,201,154,183,32,21,33,111,152,126, + 50,229,149,205,52,144,33,110,152,110,38,0, + 229,205,11,142,193,237,91,96,152,42,104,152, + 25,221,117,254,221,116,255,35,35,54,2,17, + 2,0,43,43,115,35,114,58,44,152,35,35, + 119,58,228,149,35,119,62,1,211,100,211,84, + 62,1,50,201,154,24,169,205,153,142,58,231, + 149,183,40,250,175,50,231,149,33,110,152,126, + 254,255,40,91,58,233,149,230,63,183,40,83, + 94,22,0,33,234,149,25,126,183,40,13,33, + 110,152,94,33,234,150,25,126,254,3,32,36, + 205,81,148,125,180,33,110,152,94,22,0,40, + 17,33,234,149,25,54,0,33,107,152,229,205, + 240,142,193,195,198,149,33,234,150,25,54,0, + 33,110,152,94,22,0,33,234,149,25,126,50, + 49,152,254,132,32,37,62,47,50,34,152,42, + 107,152,229,33,110,152,229,205,174,140,193,193, + 125,180,33,110,152,94,22,0,33,234,150,202, + 117,147,25,52,195,120,147,58,49,152,254,140, + 32,7,62,1,50,34,152,24,210,62,32,50, + 106,152,24,19,58,49,152,95,58,106,152,163, + 183,58,106,152,32,11,203,63,50,106,152,58, + 106,152,183,32,231,254,2,40,51,254,4,40, + 38,254,8,40,26,254,16,40,13,254,32,32, + 158,62,165,50,49,152,62,69,24,190,62,164, + 50,49,152,62,70,24,181,62,163,50,49,152, + 175,24,173,62,162,50,49,152,62,1,24,164, + 62,161,50,49,152,62,3,24,155,25,54,0, + 221,126,251,254,8,40,7,58,230,149,183,202, + 32,146,33,107,152,229,205,240,142,193,211,84, + 195,198,149,237,91,96,152,42,104,152,25,221, + 117,254,221,116,255,35,35,54,6,17,2,0, + 43,43,115,35,114,58,228,149,35,35,119,58, + 233,149,35,119,205,146,142,195,32,146,237,91, + 96,152,42,104,152,25,229,205,160,142,193,58, + 231,149,183,40,250,175,50,231,149,243,237,91, + 96,152,42,104,152,25,221,117,254,221,116,255, + 78,35,70,221,113,252,221,112,253,89,80,42, + 98,152,183,237,82,34,98,152,203,124,40,19, + 33,0,0,34,98,152,34,102,152,34,96,152, + 62,1,50,95,152,24,40,221,94,252,221,86, + 253,19,19,19,42,96,152,25,34,96,152,237, + 91,100,152,33,158,253,25,237,91,96,152,205, + 171,149,242,55,148,33,0,0,34,96,152,175, + 50,230,149,251,195,32,146,245,62,1,50,231, + 149,62,16,237,57,0,211,80,241,251,237,77, + 201,205,186,149,229,229,33,0,0,34,37,152, + 33,110,152,126,50,234,151,58,44,152,33,235, + 151,119,221,54,253,0,221,54,254,0,195,230, + 148,33,236,151,54,175,33,3,0,229,33,234, + 151,229,205,174,140,193,193,33,236,151,126,254, + 255,40,74,33,245,151,110,221,117,255,33,249, + 151,126,221,166,255,221,119,255,33,253,151,126, + 221,166,255,221,119,255,58,232,149,95,221,126, + 255,163,221,119,255,183,40,15,230,191,33,110, + 152,94,22,0,33,234,149,25,119,24,12,33, + 110,152,94,22,0,33,234,149,25,54,132,33, + 0,0,195,198,149,221,110,253,221,102,254,35, + 221,117,253,221,116,254,17,32,0,221,110,253, + 221,102,254,205,171,149,250,117,148,58,233,149, + 203,87,40,84,33,1,0,34,37,152,221,54, + 253,0,221,54,254,0,24,53,33,236,151,54, + 175,33,3,0,229,33,234,151,229,205,174,140, + 193,193,33,236,151,126,254,255,40,14,33,110, + 152,94,22,0,33,234,149,25,54,140,24,159, + 221,110,253,221,102,254,35,221,117,253,221,116, + 254,17,32,0,221,110,253,221,102,254,205,171, + 149,250,12,149,33,2,0,34,37,152,221,54, + 253,0,221,54,254,0,24,54,33,236,151,54, + 175,33,3,0,229,33,234,151,229,205,174,140, + 193,193,33,236,151,126,254,255,40,15,33,110, + 152,94,22,0,33,234,149,25,54,132,195,211, + 148,221,110,253,221,102,254,35,221,117,253,221, + 116,254,17,32,0,221,110,253,221,102,254,205, + 171,149,250,96,149,33,1,0,195,198,149,124, + 170,250,179,149,237,82,201,124,230,128,237,82, + 60,201,225,253,229,221,229,221,33,0,0,221, + 57,233,221,249,221,225,253,225,201,233,225,253, + 229,221,229,221,33,0,0,221,57,94,35,86, + 35,235,57,249,235,233,0,0,0,0,0,0, + 62,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 175,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,133,1,0,0,0,63, + 255,255,255,255,0,0,0,63,0,0,0,0, + 0,0,0,0,0,0,0,24,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + } ; + +#endif diff -u --recursive --new-file v2.1.43/linux/drivers/net/cops_ltdrv.h linux/drivers/net/cops_ltdrv.h --- v2.1.43/linux/drivers/net/cops_ltdrv.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/cops_ltdrv.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,241 @@ +/* + * The firmware this driver downloads into the Localtalk card is a + * seperate program and is not GPL'd source code, even though the Linux + * side driver and the routine that loads this data into the card are. + * + * It is taken from the COPS SDK and is under the following license + * + * This material is licensed to you strictly for use in conjunction with + * the use of COPS LocalTalk adapters. + * There is no charge for this SDK. And no waranty express or implied + * about its fitness for any purpose. However, we will cheerefully + * refund every penny you paid for this SDK... + * Regards, + * + * Thomas F. Divine + * Chief Scientist + */ + + +/* cops_ltdrv.h: LocalTalk driver firmware dump for Linux. + * + * Authors: + * - Jay Schulist + */ + + +#ifdef CONFIG_COPS_TANGENT + +unsigned char ltdrv_code[] = { + 58,3,0,50,148,10,33,143,15,62,85,119, + 190,32,9,62,170,119,190,32,3,35,24,241, + 34,146,10,249,17,150,10,33,143,15,183,237, + 82,77,68,11,107,98,19,54,0,237,176,62, + 16,237,57,51,62,0,237,57,50,237,57,54, + 62,12,237,57,49,62,195,33,39,2,50,56, + 0,34,57,0,237,86,205,30,2,251,205,60, + 10,24,169,67,111,112,121,114,105,103,104,116, + 32,40,99,41,32,49,57,56,56,45,49,57, + 57,50,44,32,80,114,105,110,116,105,110,103, + 32,67,111,109,109,117,110,105,99,97,116,105, + 111,110,115,32,65,115,115,111,99,105,97,116, + 101,115,44,32,73,110,99,46,65,108,108,32, + 114,105,103,104,116,115,32,114,101,115,101,114, + 118,101,100,46,32,32,4,4,22,40,255,60, + 4,96,10,224,6,0,7,126,2,64,11,246, + 12,6,13,0,14,193,15,0,5,96,3,192, + 1,0,9,8,62,3,211,82,62,192,211,82, + 201,62,3,211,82,62,213,211,82,201,62,5, + 211,82,62,224,211,82,201,62,5,211,82,62, + 224,211,82,201,62,5,211,82,62,96,211,82, + 201,6,28,33,180,1,14,82,237,163,194,4, + 2,33,39,2,34,64,0,58,3,0,230,1, + 192,62,11,237,121,62,118,237,121,201,33,182, + 10,54,132,205,253,1,201,245,197,213,229,42, + 150,10,14,83,17,98,2,67,20,237,162,58, + 179,1,95,219,82,230,1,32,6,29,32,247, + 195,17,3,62,1,211,82,219,82,95,230,160, + 32,10,237,162,32,225,21,32,222,195,15,3, + 237,162,123,230,96,194,21,3,62,48,211,82, + 62,1,211,82,175,211,82,237,91,150,10,43, + 55,237,82,218,19,3,34,152,10,98,107,58, + 154,10,190,32,81,62,1,50,158,10,35,35, + 62,132,190,32,44,54,133,43,70,58,154,10, + 119,43,112,17,3,0,205,137,3,62,16,211, + 82,62,56,211,82,205,217,1,42,150,10,14, + 83,17,98,2,67,20,58,178,1,95,195,59, + 2,62,129,190,194,227,2,54,130,43,70,58, + 154,10,119,43,112,17,3,0,205,137,3,195, + 254,2,35,35,126,254,132,194,227,2,205,61, + 3,24,20,62,128,166,194,222,2,221,229,221, + 33,175,10,205,93,6,205,144,7,221,225,225, + 209,193,241,251,237,77,221,229,221,33,159,10, + 205,93,6,221,225,205,61,3,195,247,2,24, + 237,24,235,24,233,230,64,40,2,24,227,24, + 225,175,50,179,10,205,208,1,201,197,33,4, + 0,57,126,35,102,111,205,51,3,193,201,62, + 1,50,179,10,34,150,10,54,0,58,179,10, + 183,200,62,14,211,82,62,193,211,82,62,10, + 211,82,62,224,211,82,62,6,211,82,58,154, + 10,211,82,62,16,211,82,62,56,211,82,62, + 48,211,82,219,82,230,1,40,4,219,83,24, + 242,62,14,211,82,62,33,211,82,62,1,211, + 82,62,9,211,82,62,32,211,82,205,217,1, + 201,14,83,205,208,1,24,23,14,83,205,208, + 1,205,226,1,58,174,1,61,32,253,205,244, + 1,58,174,1,61,32,253,205,226,1,58,175, + 1,61,32,253,62,5,211,82,62,233,211,82, + 62,128,211,82,58,176,1,61,32,253,237,163, + 27,62,192,211,82,219,82,230,4,40,250,237, + 163,27,122,179,32,243,219,82,230,4,40,250, + 58,178,1,71,219,82,230,4,40,3,5,32, + 247,219,82,230,4,40,250,205,235,1,58,177, + 1,61,32,253,205,244,1,201,229,213,35,35, + 126,230,128,194,145,4,43,58,154,10,119,43, + 70,33,181,10,119,43,112,17,3,0,243,62, + 10,211,82,219,82,230,128,202,41,4,209,225, + 62,1,55,251,201,205,144,3,58,180,10,254, + 255,202,127,4,205,217,1,58,178,1,71,219, + 82,230,1,32,6,5,32,247,195,173,4,219, + 83,71,58,154,10,184,194,173,4,58,178,1, + 71,219,82,230,1,32,6,5,32,247,195,173, + 4,219,83,58,178,1,71,219,82,230,1,32, + 6,5,32,247,195,173,4,219,83,254,133,194, + 173,4,58,179,1,24,4,58,179,1,135,61, + 32,253,209,225,205,137,3,205,61,3,183,251, + 201,209,225,243,62,10,211,82,219,82,230,128, + 202,164,4,62,1,55,251,201,205,144,3,205, + 61,3,183,251,201,209,225,62,2,55,251,201, + 243,62,14,211,82,62,33,211,82,251,201,33, + 4,0,57,94,35,86,33,2,0,57,126,35, + 102,111,221,229,34,193,10,237,83,195,10,221, + 33,171,10,205,93,6,58,185,10,50,186,10, + 58,184,10,135,50,184,10,205,112,6,254,3, + 56,16,58,185,10,135,60,230,15,50,185,10, + 175,50,184,10,24,23,58,183,10,205,112,6, + 254,3,48,13,58,185,10,203,63,50,185,10, + 62,255,50,183,10,58,185,10,50,186,10,58, + 183,10,135,50,183,10,62,32,50,187,10,50, + 188,10,6,255,219,82,230,16,32,3,5,32, + 247,205,180,4,6,40,219,82,230,16,40,3, + 5,32,247,62,10,211,82,219,82,230,128,194, + 46,5,219,82,230,16,40,214,237,95,71,58, + 186,10,160,230,15,40,32,71,14,10,62,10, + 211,82,219,82,230,128,202,119,5,205,180,4, + 195,156,5,219,82,230,16,202,156,5,13,32, + 229,16,225,42,193,10,237,91,195,10,205,252, + 3,48,7,61,202,156,5,195,197,5,221,225, + 33,0,0,201,221,33,163,10,205,93,6,58, + 188,10,61,50,188,10,40,19,58,186,10,246, + 1,50,186,10,58,183,10,246,1,50,183,10, + 195,46,5,221,225,33,1,0,201,221,33,167, + 10,205,93,6,58,184,10,246,1,50,184,10, + 58,186,10,135,246,1,50,186,10,58,187,10, + 61,50,187,10,194,46,5,221,225,33,2,0, + 201,221,229,33,0,0,57,17,4,0,25,126, + 50,154,10,230,128,50,189,10,58,189,10,183, + 40,6,221,33,88,2,24,4,221,33,150,0, + 58,154,10,183,40,49,60,40,46,61,33,190, + 10,119,35,119,35,54,129,175,50,158,10,221, + 43,221,229,225,124,181,40,42,33,190,10,17, + 3,0,205,206,4,17,232,3,27,123,178,32, + 251,58,158,10,183,40,224,58,154,10,71,62, + 7,128,230,127,71,58,189,10,176,50,154,10, + 24,166,221,225,201,183,221,52,0,192,221,52, + 1,192,221,52,2,192,221,52,3,192,55,201, + 6,8,14,0,31,48,1,12,16,250,121,201, + 33,2,0,57,94,35,86,35,78,35,70,35, + 126,35,102,105,79,120,68,103,237,176,201,33, + 2,0,57,126,35,102,111,62,17,237,57,48, + 125,237,57,40,124,237,57,41,62,0,237,57, + 42,62,64,237,57,43,62,0,237,57,44,33, + 128,2,125,237,57,46,124,237,57,47,62,145, + 237,57,48,211,68,58,149,10,211,66,201,33, + 2,0,57,126,35,102,111,62,33,237,57,48, + 62,64,237,57,32,62,0,237,57,33,237,57, + 34,125,237,57,35,124,237,57,36,62,0,237, + 57,37,33,128,2,125,237,57,38,124,237,57, + 39,62,97,237,57,48,211,67,58,149,10,211, + 66,201,237,56,46,95,237,56,47,87,237,56, + 46,111,237,56,47,103,183,237,82,32,235,33, + 128,2,183,237,82,201,237,56,38,95,237,56, + 39,87,237,56,38,111,237,56,39,103,183,237, + 82,32,235,33,128,2,183,237,82,201,205,106, + 10,221,110,6,221,102,7,126,35,110,103,195, + 118,10,205,106,10,33,0,0,34,205,10,34, + 198,10,34,200,10,33,143,15,34,207,10,237, + 91,207,10,42,146,10,183,237,82,17,0,255, + 25,34,203,10,203,124,40,6,33,0,125,34, + 203,10,42,207,10,229,205,37,3,195,118,10, + 205,106,10,229,42,150,10,35,35,35,229,205, + 70,7,193,124,230,3,103,221,117,254,221,116, + 255,237,91,152,10,35,35,35,183,237,82,32, + 12,17,5,0,42,152,10,205,91,10,242,203, + 7,42,150,10,229,205,37,3,195,118,10,237, + 91,152,10,42,200,10,25,34,200,10,42,205, + 10,25,34,205,10,237,91,203,10,33,158,253, + 25,237,91,205,10,205,91,10,242,245,7,33, + 0,0,34,205,10,62,1,50,197,10,205,5, + 8,33,0,0,57,249,195,118,10,205,106,10, + 58,197,10,183,202,118,10,237,91,198,10,42, + 205,10,205,91,10,242,46,8,237,91,205,10, + 33,98,2,25,237,91,198,10,205,91,10,250, + 78,8,237,91,198,10,42,205,10,183,237,82, + 32,7,42,200,10,125,180,40,13,237,91,205, + 10,42,198,10,205,91,10,242,97,8,237,91, + 207,10,42,205,10,25,229,205,37,3,175,50, + 197,10,195,118,10,205,29,3,33,0,0,57, + 249,195,118,10,205,106,10,58,202,10,183,40, + 22,205,14,7,237,91,209,10,19,19,19,205, + 91,10,242,139,8,33,1,0,195,118,10,33, + 0,0,195,118,10,205,126,10,252,255,205,108, + 8,125,180,194,118,10,237,91,200,10,33,0, + 0,205,91,10,242,118,10,237,91,207,10,42, + 198,10,25,221,117,254,221,116,255,35,35,35, + 229,205,70,7,193,124,230,3,103,35,35,35, + 221,117,252,221,116,253,229,221,110,254,221,102, + 255,229,33,212,10,229,205,124,6,193,193,221, + 110,252,221,102,253,34,209,10,33,211,10,54, + 4,33,209,10,227,205,147,6,193,62,1,50, + 202,10,243,221,94,252,221,86,253,42,200,10, + 183,237,82,34,200,10,203,124,40,17,33,0, + 0,34,200,10,34,205,10,34,198,10,50,197, + 10,24,37,221,94,252,221,86,253,42,198,10, + 25,34,198,10,237,91,203,10,33,158,253,25, + 237,91,198,10,205,91,10,242,68,9,33,0, + 0,34,198,10,205,5,8,33,0,0,57,249, + 251,195,118,10,205,106,10,33,49,13,126,183, + 40,16,205,42,7,237,91,47,13,19,19,19, + 205,91,10,242,117,9,58,142,15,198,1,50, + 142,15,195,118,10,33,49,13,126,254,1,40, + 25,254,3,202,7,10,254,5,202,21,10,33, + 49,13,54,0,33,47,13,229,205,207,6,195, + 118,10,58,141,15,183,32,72,33,51,13,126, + 50,149,10,205,86,7,33,50,13,126,230,127, + 183,32,40,58,142,15,230,127,50,142,15,183, + 32,5,198,1,50,142,15,33,50,13,126,111, + 23,159,103,203,125,58,142,15,40,5,198,128, + 50,142,15,33,50,13,119,33,50,13,126,111, + 23,159,103,229,205,237,5,193,33,211,10,54, + 2,33,2,0,34,209,10,58,154,10,33,212, + 10,119,58,148,10,33,213,10,119,33,209,10, + 229,205,147,6,193,24,128,42,47,13,229,33, + 50,13,229,205,191,4,193,24,239,33,211,10, + 54,6,33,3,0,34,209,10,58,154,10,33, + 212,10,119,58,148,10,33,213,10,119,33,214, + 10,54,5,33,209,10,229,205,147,6,24,200, + 205,106,10,33,49,13,54,0,33,47,13,229, + 205,207,6,33,209,10,227,205,147,6,193,205, + 80,9,205,145,8,24,248,124,170,250,99,10, + 237,82,201,124,230,128,237,82,60,201,225,253, + 229,221,229,221,33,0,0,221,57,233,221,249, + 221,225,253,225,201,233,225,253,229,221,229,221, + 33,0,0,221,57,94,35,86,35,235,57,249, + 235,233,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0 + } ; + +#endif diff -u --recursive --new-file v2.1.43/linux/drivers/net/lapbether.c linux/drivers/net/lapbether.c --- v2.1.43/linux/drivers/net/lapbether.c Thu May 29 21:53:07 1997 +++ linux/drivers/net/lapbether.c Thu Jun 26 12:33:39 1997 @@ -407,7 +407,7 @@ return 0; } -__initfunc(static int lapbeth_dev_init(struct device *dev)) +static int lapbeth_dev_init(struct device *dev) { return 0; } diff -u --recursive --new-file v2.1.43/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.1.43/linux/drivers/net/sgiseeq.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/sgiseeq.c Thu Jun 26 12:33:39 1997 @@ -0,0 +1,737 @@ +/* $Id: sgiseeq.c,v 1.1 1997/06/09 08:34:30 ralf Exp $ + * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include "sgiseeq.h" + +static char *version = + "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n"; + +static char *sgiseeqstr = "SGI Seeq8003"; + +/* If you want speed, you do something silly, it always has worked + * for me. So, with that in mind, I've decided to make this driver + * look completely like a stupid Lance from a driver architecture + * perspective. Only difference is that here our "ring buffer" looks + * and acts like a real Lance one does but is layed out like how the + * HPC DMA and the Seeq want it to. You'd be surprised how a stupid + * idea like this can pay off in performance, not to mention making + * this driver 2,000 times easier to write. ;-) + */ + +/* Tune these if we tend to run out often etc. */ +#define SEEQ_RX_BUFFERS 16 +#define SEEQ_TX_BUFFERS 16 + +#define PKT_BUF_SZ 1584 + +#define NEXT_RX(i) (((i) + 1) & (SEEQ_RX_BUFFERS - 1)) +#define NEXT_TX(i) (((i) + 1) & (SEEQ_TX_BUFFERS - 1)) +#define PREV_RX(i) (((i) - 1) & (SEEQ_RX_BUFFERS - 1)) +#define PREV_TX(i) (((i) - 1) & (SEEQ_TX_BUFFERS - 1)) + +#define TX_BUFFS_AVAIL(sp) ((sp->tx_old <= sp->tx_new) ? \ + sp->tx_old + (SEEQ_TX_BUFFERS - 1) - sp->tx_new : \ + sp->tx_old - sp->tx_new - 1) + +#define DEBUG + +struct sgiseeq_rx_desc { + struct hpc_dma_desc rdma; + unsigned long buf_vaddr; +}; + +struct sgiseeq_tx_desc { + struct hpc_dma_desc tdma; + unsigned long buf_vaddr; +}; + +/* Warning: This structure is layed out in a certain way because + * HPC dma descriptors must be 8-byte aligned. So don't + * touch this without some care. + */ +struct sgiseeq_init_block { /* Note the name ;-) */ + /* Ptrs to the descriptors in KSEG1 uncached space. */ + struct sgiseeq_rx_desc *rx_desc; + struct sgiseeq_tx_desc *tx_desc; + unsigned long _padding[14]; /* Pad out to largest cache line size. */ + + struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS]; + struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS]; +}; + +struct sgiseeq_private { + volatile struct sgiseeq_init_block srings; + char *name; + volatile struct hpc3_ethregs *hregs; + volatile struct sgiseeq_regs *sregs; + + /* Ring entry counters. */ + unsigned int rx_new, tx_new; + unsigned int rx_old, tx_old; + + int is_edlc; + unsigned char control; + unsigned char mode; + + struct enet_statistics stats; +}; + +static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs) +{ + hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ); + udelay(20); + hregs->rx_reset = 0; +} + +static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs, + volatile struct sgiseeq_regs *sregs) +{ + hregs->rx_ctrl = hregs->tx_ctrl = 0; + hpc3_eth_reset(hregs); +} + +#define RSTAT_GO_BITS (SEEQ_RCMD_IGOOD | SEEQ_RCMD_IEOF | SEEQ_RCMD_ISHORT | \ + SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC) + +static inline void seeq_go(struct sgiseeq_private *sp, + volatile struct hpc3_ethregs *hregs, + volatile struct sgiseeq_regs *sregs) +{ + sregs->rstat = sp->mode | RSTAT_GO_BITS; + hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE; +} + +static inline void seeq_load_eaddr(struct device *dev, + volatile struct sgiseeq_regs *sregs) +{ + int i; + + sregs->tstat = SEEQ_TCMD_RB0; + for(i = 0; i < 6; i++) + sregs->rw.eth_addr[i] = dev->dev_addr[i]; +} + +#define TCNTINFO_INIT (HPCDMA_EOX | HPCDMA_ETXD) +#define RCNTCFG_INIT (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE) +#define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT)) + +static void seeq_init_ring(struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + volatile struct sgiseeq_init_block *ib = &sp->srings; + int i; + + dev->tbusy = 1; + sp->rx_new = sp->tx_new = 0; + sp->rx_old = sp->tx_old = 0; + + seeq_load_eaddr(dev, sp->sregs); + + /* XXX for now just accept packets directly to us + * XXX and ether-broadcast. Will do multicast and + * XXX promiscuous mode later. -davem + */ + sp->mode = SEEQ_RCMD_RBCAST; + + /* Setup tx ring. */ + for(i = 0; i < SEEQ_TX_BUFFERS; i++) { + if(!ib->tx_desc[i].tdma.pbuf) { + unsigned long buffer; + + buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); + ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer); + flush_cache_all(); + } + ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT); + } + + /* And now the rx ring. */ + for(i = 0; i < SEEQ_RX_BUFFERS; i++) { + if(!ib->rx_desc[i].rdma.pbuf) { + unsigned long buffer; + + buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); + ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer); + flush_cache_all(); + } + ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT); + } + ib->rx_desc[i - 1].rdma.cntinfo |= (HPCDMA_EOR); +} + +#ifdef DEBUG +static struct sgiseeq_private *gpriv; +static struct device *gdev; + +void sgiseeq_dump_rings(void) +{ + static int once = 0; + struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc; + struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc; + volatile struct hpc3_ethregs *hregs = gpriv->hregs; + int i; + + if(once) + return; + once++; + printk("RING DUMP:\n"); + for(i = 0; i < SEEQ_RX_BUFFERS; i++) { + printk("RX [%d]: @(%p) [%08lx,%08lx,%08lx] ", + i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo, + r[i].rdma.pnext); + i += 1; + printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n", + i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo, + r[i].rdma.pnext); + } + for(i = 0; i < SEEQ_TX_BUFFERS; i++) { + printk("TX [%d]: @(%p) [%08lx,%08lx,%08lx] ", + i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo, + t[i].tdma.pnext); + i += 1; + printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n", + i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo, + t[i].tdma.pnext); + } + printk("INFO: [rx_new = %d rx_old=%d] [tx_new = %d tx_old = %d]\n", + gpriv->rx_new, gpriv->rx_old, gpriv->tx_new, gpriv->tx_old); + printk("RREGS: rx_cbptr[%08lx] rx_ndptr[%08lx] rx_ctrl[%08lx]\n", + hregs->rx_cbptr, hregs->rx_ndptr, hregs->rx_ctrl); + printk("TREGS: tx_cbptr[%08lx] tx_ndptr[%08lx] tx_ctrl[%08lx]\n", + hregs->tx_cbptr, hregs->tx_ndptr, hregs->tx_ctrl); +} +#endif + +#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF) +#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2) +#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ) + +static void init_seeq(struct device *dev, struct sgiseeq_private *sp, + volatile struct sgiseeq_regs *sregs) +{ + volatile struct hpc3_ethregs *hregs = sp->hregs; + + reset_hpc3_and_seeq(hregs, sregs); + seeq_init_ring(dev); + + /* Setup to field the proper interrupt types. */ + if(sp->is_edlc) { + sregs->tstat = (TSTAT_INIT_EDLC); + sregs->rw.wregs.control = sp->control; + sregs->rw.wregs.frame_gap = 0; + } else { + sregs->tstat = (TSTAT_INIT_SEEQ); + } + + hregs->rx_dconfig |= RDMACFG_INIT; + + hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[0]); + hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[0]); + + seeq_go(sp, hregs, sregs); +} + +static inline void record_rx_errors(struct sgiseeq_private *sp, + unsigned char status) +{ + if(status & SEEQ_RSTAT_OVERF || + status & SEEQ_RSTAT_SFRAME) + sp->stats.rx_over_errors++; + if(status & SEEQ_RSTAT_CERROR) + sp->stats.rx_crc_errors++; + if(status & SEEQ_RSTAT_DERROR) + sp->stats.rx_frame_errors++; + if(status & SEEQ_RSTAT_REOF) + sp->stats.rx_errors++; +} + +static inline void rx_maybe_restart(struct sgiseeq_private *sp, + volatile struct hpc3_ethregs *hregs, + volatile struct sgiseeq_regs *sregs) +{ + if(!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) { + hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]); + seeq_go(sp, hregs, sregs); + } +} + +#define for_each_rx(rd, sp) for((rd) = &(sp)->srings.rx_desc[(sp)->rx_new]; \ + !((rd)->rdma.cntinfo & HPCDMA_OWN); \ + (rd) = &(sp)->srings.rx_desc[(sp)->rx_new]) + +static inline void sgiseeq_rx(struct device *dev, struct sgiseeq_private *sp, + volatile struct hpc3_ethregs *hregs, + volatile struct sgiseeq_regs *sregs) +{ + struct sgiseeq_rx_desc *rd; + struct sk_buff *skb = 0; + unsigned char pkt_status; + unsigned char *pkt_pointer = 0; + int len = 0; + unsigned int orig_end = PREV_RX(sp->rx_new); + + /* Service every received packet. */ + for_each_rx(rd, sp) { + len = (PKT_BUF_SZ - (rd->rdma.cntinfo & HPCDMA_BCNT) - 3); + pkt_pointer = (unsigned char *)rd->buf_vaddr; + pkt_status = pkt_pointer[len + 2]; + + if(pkt_status & SEEQ_RSTAT_FIG) { + /* Packet is OK. */ + skb = dev_alloc_skb(len + 2); + + if(skb) { + skb->dev = dev; + skb_reserve(skb, 2); + skb_put(skb, len); + + /* Copy out of kseg1 to avoid silly cache flush. */ + eth_copy_and_sum(skb, pkt_pointer + 2, len, 0); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + sp->stats.rx_packets++; + } else { + printk ("%s: Memory squeeze, deferring packet.\n", + dev->name); + sp->stats.rx_dropped++; + } + } else { + record_rx_errors(sp, pkt_status); + } + + /* Return the entry to the ring pool. */ + rd->rdma.cntinfo = (RCNTINFO_INIT); + sp->rx_new = NEXT_RX(sp->rx_new); + } + sp->srings.rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); + sp->srings.rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; + rx_maybe_restart(sp, hregs, sregs); +} + +static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp, + volatile struct sgiseeq_regs *sregs) +{ + if(sp->is_edlc) { + sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT); + sregs->rw.wregs.control = sp->control; + } +} + +static inline void sgiseeq_tx(struct device *dev, struct sgiseeq_private *sp, + volatile struct hpc3_ethregs *hregs, + volatile struct sgiseeq_regs *sregs) +{ + struct sgiseeq_tx_desc *td; + unsigned long status = hregs->tx_ctrl; + int j; + + tx_maybe_reset_collisions(sp, sregs); + + if(!(status & HPC3_ETXCTRL_ACTIVE)) { + if(!(status & SEEQ_TSTAT_PTRANS)) { + /* Oops, HPC detected some sort of error. */ + if(status & SEEQ_TSTAT_R16) + sp->stats.tx_aborted_errors++; + if(status & SEEQ_TSTAT_UFLOW) + sp->stats.tx_fifo_errors++; + if(status & SEEQ_TSTAT_LCLS) + sp->stats.collisions++; + } + /* If the HPC aint doin nothin, and there are more packets + * with ETXD cleared and XIU set we must make very certain + * that we restart the HPC else we risk locking up the + * adapter. The following read of tx_ndptr is only safe + * iff the HPCDMA is not active! + */ + td = (struct sgiseeq_tx_desc *) + KSEG1ADDR(((hregs->tx_ndptr) & ~0xf)); + while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) == + (HPCDMA_XIU | HPCDMA_ETXD)) + td = (struct sgiseeq_tx_desc *) + KSEG1ADDR(td->tdma.pnext); + if(td->tdma.cntinfo & HPCDMA_XIU) { + hregs->tx_ndptr = PHYSADDR(td); + hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; + } + } + + /* Ack 'em... */ + for(j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) { + td = &sp->srings.tx_desc[j]; + + if(!(td->tdma.cntinfo & (HPCDMA_XIU))) + break; + if(!(td->tdma.cntinfo & (HPCDMA_ETXD))) + break; + sp->stats.tx_packets++; + sp->tx_old = NEXT_TX(sp->tx_old); + td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE); + td->tdma.cntinfo |= HPCDMA_EOX; + } +} + +static inline void tx_maybe_unbusy(struct sgiseeq_private *sp, + struct device *dev) +{ + if((TX_BUFFS_AVAIL(sp) >= 0) && dev->tbusy) { + dev->tbusy = 0; + mark_bh(NET_BH); + } +} + +static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + volatile struct hpc3_ethregs *hregs = sp->hregs; + volatile struct sgiseeq_regs *sregs = sp->sregs; + + /* Ack the IRQ and set software state. */ + hregs->rx_reset = HPC3_ERXRST_CLRIRQ; + dev->interrupt = 1; + + /* Always check for received packets. */ + sgiseeq_rx(dev, sp, hregs, sregs); + + /* Only check for tx acks iff we have something queued. */ + if(sp->tx_old != sp->tx_new) + sgiseeq_tx(dev, sp, hregs, sregs); + + tx_maybe_unbusy(sp, dev); + dev->interrupt = 0; +} + +static int sgiseeq_open(struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv; + volatile struct sgiseeq_regs *sregs = sp->sregs; + unsigned long flags; + + save_flags(flags); cli(); + if(request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, (void *) dev)) { + printk("Seeq8003: Can't get irq %d\n", dev->irq); + restore_flags(flags); + return -EAGAIN; + } + + init_seeq(dev, sp, sregs); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + restore_flags(flags); + return 0; +} + +static int sgiseeq_close(struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + volatile struct sgiseeq_regs *sregs = sp->sregs; + + dev->start = 0; + dev->tbusy = 1; + + /* Shutdown the Seeq. */ + reset_hpc3_and_seeq(sp->hregs, sregs); + + free_irq(dev->irq, NULL); + + return 0; +} + +static inline int sgiseeq_reset(struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + volatile struct sgiseeq_regs *sregs = sp->sregs; + + init_seeq(dev, sp, sregs); + + dev->trans_start = jiffies; + dev->interrupt = 0; + dev->start = 1; + dev->tbusy = 0; + + return 0; +} + +void sgiseeq_my_reset(void) +{ + printk("RESET!\n"); + sgiseeq_reset(gdev); +} + +static inline int verify_tx(struct sgiseeq_private *sp, + struct device *dev, + struct sk_buff *skb) +{ + /* Are we bolixed? */ + if(dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + + printk("%s: transmit timed out, ticks=%d resetting\n", + dev->name, tickssofar); + sgiseeq_reset(dev); + return 0; + } + /* Is the skippy buf even reasonable? */ + if(skb == NULL) { + dev_tint(dev); + printk("%s: skb is NULL\n", dev->name); + return -1; + } + + if(skb->len <= 0) { + printk("%s: skb len is %ld\n", dev->name, skb->len); + return -1; + } + /* Are we getting in someone else's way? */ + if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return -1; + } + + /* Can we even send anything? */ + if(!TX_BUFFS_AVAIL(sp)) + return -1; + + return 0; +} + +static int sgiseeq_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + volatile struct hpc3_ethregs *hregs = sp->hregs; + unsigned long flags; + struct sgiseeq_tx_desc *td; + int skblen, len, entry; + + if(verify_tx(sp, dev, skb)) + return -1; /* Yeee... */ + + save_flags(flags); cli(); + + /* Setup... */ + skblen = skb->len; + len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + entry = sp->tx_new; + td = &sp->srings.tx_desc[entry]; + + /* Create entry. There are so many races with adding a new + * descriptor to the chain: + * 1) Assume that the HPC is off processing a DMA chain while + * we are changing all of the following. + * 2) Do no allow the HPC to look at a new descriptor until + * we have completely set up it's state. This means, do + * not clear HPCDMA_EOX in the current last descritptor + * until the one we are adding looks consistant and could + * be processes right now. + * 3) The tx interrupt code must notice when we've added a new + * entry and the HPC got to the end of the chain before we + * added this new entry and restarted it. + */ + memcpy((char *)td->buf_vaddr, skb->data, skblen); + td->tdma.cntinfo = ((len) & HPCDMA_BCNT) | + (HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX); + if(sp->tx_old != sp->tx_new) { + struct sgiseeq_tx_desc *backend; + + backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)]; + backend->tdma.cntinfo &= ~(HPCDMA_EOX); + } + sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ + + /* Maybe kick the HPC back into motion. */ + if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) { + hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[sp->tx_old]); + hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; + } + dev->trans_start = jiffies; + dev_kfree_skb(skb, FREE_WRITE); + + if(TX_BUFFS_AVAIL(sp)) + dev->tbusy = 0; + restore_flags(flags); + return 0; +} + +static struct enet_statistics *sgiseeq_get_stats(struct device *dev) +{ + struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; + + return &sp->stats; +} + +static void sgiseeq_set_multicast(struct device *dev) +{ +} + +static inline void setup_tx_ring(struct sgiseeq_tx_desc *buf, int nbufs) +{ + int i = 0; + + while(i < (nbufs - 1)) { + buf[i].tdma.pnext = PHYSADDR(&buf[i + 1]); + buf[i].tdma.pbuf = 0; + i++; + } + buf[i].tdma.pnext = PHYSADDR(&buf[0]); +} + +static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs) +{ + int i = 0; + + while(i < (nbufs - 1)) { + buf[i].rdma.pnext = PHYSADDR(&buf[i + 1]); + buf[i].rdma.pbuf = 0; + i++; + } + buf[i].rdma.pbuf = 0; + buf[i].rdma.pnext = PHYSADDR(&buf[0]); +} + +static char onboard_eth_addr[6]; + +#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) + +int sgiseeq_init(struct device *dev, struct sgiseeq_regs *sregs, + struct hpc3_ethregs *hregs, int irq) +{ + static unsigned version_printed = 0; + int i; + struct sgiseeq_private *sp; + + if(dev == NULL) { + dev = init_etherdev(0, sizeof(struct sgiseeq_private)); + } else { + dev->priv = (struct sgiseeq_private *) get_free_page(GFP_KERNEL); + if(dev->priv == NULL) + return -ENOMEM; + } + + if(!version_printed++) + printk(version); + + printk("%s: SGI Seeq8003 ", dev->name); + + for(i = 0; i < 6; i++) + printk("%2.2x%c", + dev->dev_addr[i] = onboard_eth_addr[i], + i == 5 ? ' ': ':'); + + printk("\n"); + + sp = (struct sgiseeq_private *) dev->priv; +#ifdef DEBUG + gpriv = sp; + gdev = dev; +#endif + memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private)); + sp->sregs = sregs; + sp->hregs = hregs; + sp->name = sgiseeqstr; + + sp->srings.rx_desc = (struct sgiseeq_rx_desc *) + (KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0]))); + sp->srings.tx_desc = (struct sgiseeq_tx_desc *) + (KSEG1ADDR(ALIGNED(&sp->srings.txvector[0]))); + flush_cache_all(); + + /* A couple calculations now, saves many cycles later. */ + setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS); + setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS); + flush_cache_all(); + + /* Reset the chip. */ + hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs); + + sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff); + if(sp->is_edlc) { + sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT | + SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT | + SEEQ_CTRL_ENCARR); + } + + dev->open = sgiseeq_open; + dev->stop = sgiseeq_close; + dev->hard_start_xmit = sgiseeq_start_xmit; + dev->get_stats = sgiseeq_get_stats; + dev->set_multicast_list = sgiseeq_set_multicast; + dev->irq = irq; + dev->dma = 0; + ether_setup(dev); + return 0; +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if(*str == ':') + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int sgiseeq_probe(struct device *dev) +{ + char *ep; + + /* First get the ethernet address of the onboard + * interface from ARCS. + */ + ep = romvec->get_evar("eaddr"); + str2eaddr(onboard_eth_addr, ep); + return sgiseeq_init(dev, + (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)), + &hpc3c0->ethregs, 3); + +} diff -u --recursive --new-file v2.1.43/linux/drivers/net/sgiseeq.h linux/drivers/net/sgiseeq.h --- v2.1.43/linux/drivers/net/sgiseeq.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/sgiseeq.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,103 @@ +/* $Id: sgiseeq.h,v 1.1 1997/06/09 08:34:32 ralf Exp $ + * sgiseeq.h: Defines for the Seeq8003 ethernet controller. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _SGISEEQ_H +#define _SGISEEQ_H + +struct sgiseeq_wregs { + volatile unsigned long multicase_high[2]; + volatile unsigned long frame_gap; + volatile unsigned long control; +}; + +struct sgiseeq_rregs { + volatile unsigned long collision_tx[2]; + volatile unsigned long collision_all[2]; + volatile unsigned long _unused0; + volatile unsigned long rflags; +}; + +struct sgiseeq_regs { + union { + volatile unsigned long eth_addr[6]; + volatile unsigned long multicast_low[6]; + struct sgiseeq_wregs wregs; + struct sgiseeq_rregs rregs; + } rw; + volatile unsigned long rstat; + volatile unsigned long tstat; +}; + +/* Seeq8003 receive status register */ +#define SEEQ_RSTAT_OVERF 0x001 /* Overflow */ +#define SEEQ_RSTAT_CERROR 0x002 /* CRC error */ +#define SEEQ_RSTAT_DERROR 0x004 /* Dribble error */ +#define SEEQ_RSTAT_SFRAME 0x008 /* Short frame */ +#define SEEQ_RSTAT_REOF 0x010 /* Received end of frame */ +#define SEEQ_RSTAT_FIG 0x020 /* Frame is good */ +#define SEEQ_RSTAT_TIMEO 0x040 /* Timeout, or late receive */ +#define SEEQ_RSTAT_WHICH 0x080 /* Which status, 1=old 0=new */ +#define SEEQ_RSTAT_LITTLE 0x100 /* DMA is done in little endian format */ +#define SEEQ_RSTAT_SDMA 0x200 /* DMA has started */ +#define SEEQ_RSTAT_ADMA 0x400 /* DMA is active */ +#define SEEQ_RSTAT_ROVERF 0x800 /* Receive buffer overflow */ + +/* Seeq8003 receive command register */ +#define SEEQ_RCMD_RDISAB 0x000 /* Disable receiver on the Seeq8003 */ +#define SEEQ_RCMD_IOVERF 0x001 /* IRQ on buffer overflows */ +#define SEEQ_RCMD_ICRC 0x002 /* IRQ on CRC errors */ +#define SEEQ_RCMD_IDRIB 0x004 /* IRQ on dribble errors */ +#define SEEQ_RCMD_ISHORT 0x008 /* IRQ on short frames */ +#define SEEQ_RCMD_IEOF 0x010 /* IRQ on end of frame */ +#define SEEQ_RCMD_IGOOD 0x020 /* IRQ on good frames */ +#define SEEQ_RCMD_RANY 0x040 /* Receive any frame */ +#define SEEQ_RCMD_RBCAST 0x080 /* Receive broadcasts */ +#define SEEQ_RCMD_RBMCAST 0x0c0 /* Receive broadcasts/multicasts */ + +/* Seeq8003 transmit status register */ +#define SEEQ_TSTAT_UFLOW 0x001 /* Transmit buffer underflow */ +#define SEEQ_TSTAT_CLS 0x002 /* Collision detected */ +#define SEEQ_TSTAT_R16 0x004 /* Did 16 retries to tx a frame */ +#define SEEQ_TSTAT_PTRANS 0x008 /* Packet was transmitted ok */ +#define SEEQ_TSTAT_LCLS 0x010 /* Late collision occurred */ +#define SEEQ_TSTAT_WHICH 0x080 /* Which status, 1=old 0=new */ +#define SEEQ_TSTAT_TLE 0x100 /* DMA is done in little endian format */ +#define SEEQ_TSTAT_SDMA 0x200 /* DMA has started */ +#define SEEQ_TSTAT_ADMA 0x400 /* DMA is active */ + +/* Seeq8003 transmit command register */ +#define SEEQ_TCMD_RB0 0x00 /* Register bank zero w/station addr */ +#define SEEQ_TCMD_IUF 0x01 /* IRQ on tx underflow */ +#define SEEQ_TCMD_IC 0x02 /* IRQ on collisions */ +#define SEEQ_TCMD_I16 0x04 /* IRQ after 16 failed attempts to tx frame */ +#define SEEQ_TCMD_IPT 0x08 /* IRQ when packet successfully transmitted */ +#define SEEQ_TCMD_RB1 0x20 /* Register bank one w/multi-cast low byte */ +#define SEEQ_TCMD_RB2 0x40 /* Register bank two w/multi-cast high byte */ + +/* Seeq8003 control register */ +#define SEEQ_CTRL_XCNT 0x01 +#define SEEQ_CTRL_ACCNT 0x02 +#define SEEQ_CTRL_SFLAG 0x04 +#define SEEQ_CTRL_EMULTI 0x08 +#define SEEQ_CTRL_ESHORT 0x10 +#define SEEQ_CTRL_ENCARR 0x20 + +/* Seeq8003 control registers on the SGI Hollywood HPC. */ +#define SEEQ_HPIO_P1BITS 0x00000001 /* cycles to stay in P1 phase for PIO */ +#define SEEQ_HPIO_P2BITS 0x00000060 /* cycles to stay in P2 phase for PIO */ +#define SEEQ_HPIO_P3BITS 0x00000100 /* cycles to stay in P3 phase for PIO */ +#define SEEQ_HDMA_D1BITS 0x00000006 /* cycles to stay in D1 phase for DMA */ +#define SEEQ_HDMA_D2BITS 0x00000020 /* cycles to stay in D2 phase for DMA */ +#define SEEQ_HDMA_D3BITS 0x00000000 /* cycles to stay in D3 phase for DMA */ +#define SEEQ_HDMA_TIMEO 0x00030000 /* cycles for DMA timeout */ +#define SEEQ_HCTL_NORM 0x00000000 /* Normal operation mode */ +#define SEEQ_HCTL_RESET 0x00000001 /* Reset Seeq8003 and HPC interface */ +#define SEEQ_HCTL_IPEND 0x00000002 /* IRQ is pending for the chip */ +#define SEEQ_HCTL_IPG 0x00001000 /* Inter-packet gap */ +#define SEEQ_HCTL_RFIX 0x00002000 /* At rxdc, clear end-of-packet */ +#define SEEQ_HCTL_EFIX 0x00004000 /* fixes intr status bit settings */ +#define SEEQ_HCTL_IFIX 0x00008000 /* enable startup timeouts */ + +#endif /* !(_SGISEEQ_H) */ diff -u --recursive --new-file v2.1.43/linux/drivers/net/sonic.c linux/drivers/net/sonic.c --- v2.1.43/linux/drivers/net/sonic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/sonic.c Thu Jun 26 12:33:39 1997 @@ -0,0 +1,890 @@ +/* + * sonic.c + * + * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de) + * + * This driver is based on work from Andreas Busse, but most of + * the code is rewritten. + * + * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) + * + * A driver for the onboard Sonic ethernet controller on Mips Jazz + * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and + * perhaps others, too) + */ + +static const char *version = + "sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n"; + +/* + * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook, + * National Semiconductors data sheet for the DP83932B Sonic Ethernet + * controller, and the files "8390.c" and "skeleton.c" in this directory. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sonic.h" + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef SONIC_DEBUG +static unsigned int sonic_debug = SONIC_DEBUG; +#else +static unsigned int sonic_debug = 2; +#endif + +/* + * Some tunables for the buffer areas. Power of 2 is required + * the current driver uses one receive buffer for each descriptor. + */ +#define SONIC_NUM_RRS 16 /* number of receive resources */ +#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ +#define SONIC_NUM_TDS 16 /* number of transmit descriptors */ +#define SONIC_RBSIZE 1520 /* size of one resource buffer */ + +#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) +#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) + +/* + * Base address and interupt of the SONIC controller on JAZZ boards + */ +static struct { + unsigned int port; + unsigned int irq; + } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; + + +/* Information that need to be kept for each board. */ +struct sonic_local { + sonic_cda_t cda; /* virtual CPU address of CDA */ + sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */ + sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource arrea */ + sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */ + struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */ + unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */ + unsigned char *rba; /* start of receive buffer areas */ + unsigned int cda_laddr; /* logical DMA address of CDA */ + unsigned int tda_laddr; /* logical DMA address of TDA */ + unsigned int rra_laddr; /* logical DMA address of RRA */ + unsigned int rda_laddr; /* logical DMA address of RDA */ + unsigned int rba_laddr; /* logical DMA address of RBA */ + unsigned int cur_tx, cur_rx; /* current indexes to resource areas */ + unsigned int dirty_tx,cur_rra; /* last unacked transmit packet */ + char tx_full; + struct enet_statistics stats; +}; + +/* + * We cannot use station (ethernet) address prefixes to detect the + * sonic controller since these are board manufacturer depended. + * So we check for known Silicon Revision IDs instead. + */ +static unsigned short known_revisions[] = +{ + 0x04, /* Mips Magnum 4000 */ + 0xffff /* end of list */ +}; + +/* Index to functions, as function prototypes. */ + +extern int sonic_probe(struct device *dev); +static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq); +static int sonic_open(struct device *dev); +static int sonic_send_packet(struct sk_buff *skb, struct device *dev); +static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void sonic_rx(struct device *dev); +static int sonic_close(struct device *dev); +static struct enet_statistics *sonic_get_stats(struct device *dev); +static void sonic_multicast_list(struct device *dev); +static int sonic_init(struct device *dev); + + +/* + * Probe for a SONIC ethernet controller on a Mips Jazz board. + * Actually probing is superfluous but we're paranoid. + */ +__initfunc(int sonic_probe(struct device *dev)) +{ + unsigned int base_addr = dev ? dev->base_addr : 0; + int i; + + /* + * Don't probe if we're not running on a Jazz board. + */ + if (mips_machgroup != MACH_GROUP_JAZZ) + return -ENODEV; + if (base_addr > 0x1ff) /* Check a single specified location. */ + return sonic_probe1(dev, base_addr, dev->irq); + else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; + + for (i = 0; sonic_portlist[i].port; i++) { + int base_addr = sonic_portlist[i].port; + if (check_region(base_addr, 0x100)) + continue; + if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) + return 0; + } + return -ENODEV; +} + +__initfunc(static int sonic_probe1(struct device *dev, + unsigned int base_addr, unsigned int irq)) +{ + static unsigned version_printed = 0; + unsigned int silicon_revision; + unsigned int val; + struct sonic_local *lp; + int i; + + /* + * get the Silicon Revision ID. If this is one of the known + * one assume that we found a SONIC ethernet controller at + * the expected location. + */ + silicon_revision = SONIC_READ(SONIC_SR); + if (sonic_debug > 1) + printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); + + i = 0; + while ((known_revisions[i] != 0xffff) && + (known_revisions[i] != silicon_revision)) + i++; + + if (known_revisions[i] == 0xffff) { + printk("SONIC ethernet controller not found (0x%4x)\n", + silicon_revision); + return -ENODEV; + } + + request_region(base_addr, 0x100, "SONIC"); + + /* Allocate a new 'dev' if needed. */ + if (dev == NULL) + dev = init_etherdev(0, sizeof(struct sonic_local)); + + if (sonic_debug && version_printed++ == 0) + printk(version); + + printk("%s: %s found at 0x%08x, ", + dev->name, "SONIC ethernet", base_addr); + + /* Fill in the 'dev' fields. */ + dev->base_addr = base_addr; + dev->irq = irq; + + /* + * Put the sonic into software reset, then + * retrieve and print the ethernet address. + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP,0); + for (i=0; i<3; i++) { + val = SONIC_READ(SONIC_CAP0-i); + dev->dev_addr[i*2] = val; + dev->dev_addr[i*2+1] = val >> 8; + } + + printk("HW Address "); + for (i = 0; i < 6; i++) { + printk("%2.2x", dev->dev_addr[i]); + if (i<5) + printk(":"); + } + + printk(" IRQ %d\n", irq); + + /* Initialize the device structure. */ + if (dev->priv == NULL) { + /* + * the memory be located in the same 64kb segment + */ + lp = NULL; + i = 0; + do { + lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); + if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { + /* FIXME, free the memory later */ + kfree (lp); + lp = NULL; + } + } while (lp == NULL && i++ < 20); + + if (lp == NULL) { + printk ("%s: couldn't allocate memory for descriptors\n", + dev->name); + return -ENOMEM; + } + + memset(lp, 0, sizeof(struct sonic_local)); + + /* get the virtual dma address */ + lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); + if (lp->cda_laddr == ~0UL) { + printk ("%s: couldn't get DMA page entry for descriptors\n", + dev->name); + return -ENOMEM; + } + + lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); + lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); + lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); + + /* allocate receive buffer area */ + /* FIXME, maybe we should use skbs */ + if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { + printk ("%s: couldn't allocate receive buffers\n",dev->name); + return -ENOMEM; + } + + /* get virtual dma address */ + if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { + printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); + return -ENOMEM; + } + + /* now convert pointer to KSEG1 pointer */ + lp->rba = (char *)KSEG1ADDR(lp->rba); + flush_cache_all(); + dev->priv = (struct sonic_local *)KSEG1ADDR(lp); + } + + lp = (struct sonic_local *)dev->priv; + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; +} + +/* + * Open/initialize the SONIC controller. + * + * This routine should set everything up anew at each open, even + * registers that "should" only need to be set once at boot, so that + * there is non-reboot way to recover if something goes wrong. + */ +static int sonic_open(struct device *dev) +{ + if (sonic_debug > 2) + printk("sonic_open: initializing sonic driver.\n"); + + /* + * We don't need to deal with auto-irq stuff since we + * hardwire the sonic interrupt. + */ +/* + * XXX Horrible work around: We install sonic_interrupt as fast interrupt. + * This means that during execution of the handler interrupt are disabled + * covering another bug otherwise corrupting data. This doesn't mean + * this glue works ok under all situations. + */ +// if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { + if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { + printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq); + return EAGAIN; + } + + /* + * Initialize the SONIC + */ + sonic_init(dev); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + if (sonic_debug > 2) + printk("sonic_open: Initialization done.\n"); + + return 0; +} + + +/* + * Close the SONIC device + */ +static int +sonic_close(struct device *dev) +{ + unsigned int base_addr = dev->base_addr; + + if (sonic_debug > 2) + printk ("sonic_close\n"); + + dev->tbusy = 1; + dev->start = 0; + + /* + * stop the SONIC, disable interrupts + */ + SONIC_WRITE(SONIC_ISR,0x7fff); + SONIC_WRITE(SONIC_IMR,0); + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + + free_irq(dev->irq, dev); /* release the IRQ */ + + return 0; +} + + +/* + * transmit packet + */ +static int sonic_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct sonic_local *lp = (struct sonic_local *)dev->priv; + unsigned int base_addr = dev->base_addr; + unsigned int laddr; + int entry,length; + + if (sonic_debug > 2) + printk("sonic_send_packet: skb=%p, dev=%p\n",skb,dev); + + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + + if (sonic_debug > 1) + printk("sonic_send_packet: called with dev->tbusy = 1 !\n"); + + if (tickssofar < 5) + return 1; + + printk("%s: transmit timed out.\n", dev->name); + + /* Try to restart the adaptor. */ + sonic_init(dev); + dev->tbusy=0; + dev->trans_start = jiffies; + } + + /* + * If some higher layer thinks we've missed an tx-done interrupt + * we are passed NULL. Caution: dev_tint() handles the cli()/sti() + * itself. + */ + if (skb == NULL) { + dev_tint(dev); + return 0; + } + + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + /* + * Map the packet data into the logical DMA address space + */ + if ((laddr = vdma_alloc(PHYSADDR(skb->data),skb->len)) == ~0UL) { + printk("%s: no VDMA entry for transmit available.\n",dev->name); + dev_kfree_skb(skb,FREE_WRITE); + dev->tbusy = 0; + return 1; + } + entry = lp->cur_tx & SONIC_TDS_MASK; + lp->tx_laddr[entry] = laddr; + lp->tx_skb[entry] = skb; + + length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; + flush_cache_all(); + + /* + * Setup the transmit descriptor and issue the transmit command. + */ + lp->tda[entry].tx_status = 0; /* clear status */ + lp->tda[entry].tx_frag_count = 1; /* single fragment */ + lp->tda[entry].tx_pktsize = length; /* length of packet */ + lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff; + lp->tda[entry].tx_frag_ptr_h = laddr >> 16; + lp->tda[entry].tx_frag_size = length; + + /* if there are already packets queued, allow sending serveral packets at once */ + if (lp->dirty_tx != lp->cur_tx) + lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS; + + lp->cur_tx++; + + if (sonic_debug > 2) + printk("sonic_send_packet: issueing Tx command\n"); + + SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP); + + dev->trans_start = jiffies; + + if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS) + dev->tbusy = 0; + else + lp->tx_full = 1; + + return 0; +} + + +/* + * The typical workload of the driver: + * Handle the network interface interrupts. + */ +static void +sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct device *dev = (struct device *)dev_id; + unsigned int base_addr = dev->base_addr; + struct sonic_local *lp; + int status; + + if (dev == NULL) { + printk ("sonic_interrupt: irq %d for unknown device.\n", irq); + return; + } + dev->interrupt = 1; + lp = (struct sonic_local *)dev->priv; + + status = SONIC_READ(SONIC_ISR); + SONIC_WRITE(SONIC_ISR,0x7fff); /* clear all bits */ + + if (sonic_debug > 2) + printk("sonic_interrupt: ISR=%x\n",status); + + if (status & SONIC_INT_PKTRX) { + sonic_rx(dev); /* got packet(s) */ + } + + if (status & SONIC_INT_TXDN) { + int dirty_tx = lp->dirty_tx; + + while (dirty_tx < lp->cur_tx) { + int entry = dirty_tx & SONIC_TDS_MASK; + int status = lp->tda[entry].tx_status; + + if (sonic_debug > 3) + printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n", + status,lp->cur_tx,lp->dirty_tx); + + if (status == 0) + break; /* It still hasn't been Txed */ + + /* put back EOL and free descriptor */ + lp->tda[entry].link |= SONIC_END_OF_LINKS; + lp->tda[entry].tx_status = 0; + + if (status & 0x0001) + lp->stats.tx_packets++; + else { + lp->stats.tx_errors++; + if (status & 0x0642) lp->stats.tx_aborted_errors++; + if (status & 0x0180) lp->stats.tx_carrier_errors++; + if (status & 0x0020) lp->stats.tx_window_errors++; + if (status & 0x0004) lp->stats.tx_fifo_errors++; + } + + /* We must free the original skb */ + if (lp->tx_skb[entry]) { + dev_kfree_skb(lp->tx_skb[entry],FREE_WRITE); + lp->tx_skb[entry] = 0; + } + /* and the VDMA address */ + vdma_free(lp->tx_laddr[entry]); + dirty_tx++; + } + + if (lp->tx_full && dev->tbusy + && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + + lp->dirty_tx = dirty_tx; + } + + /* + * check error conditions + */ + if (status & SONIC_INT_RFO) { + printk ("%s: receive fifo underrun\n",dev->name); + lp->stats.rx_fifo_errors++; + } + if (status & SONIC_INT_RDE) { + printk ("%s: receive descriptors exhausted\n",dev->name); + lp->stats.rx_dropped++; + } + if (status & SONIC_INT_RBE) { + printk ("%s: receive buffer exhausted\n",dev->name); + lp->stats.rx_dropped++; + } + if (status & SONIC_INT_RBAE) { + printk ("%s: receive buffer area exhausted\n",dev->name); + lp->stats.rx_dropped++; + } + + /* counter overruns; all counters are 16bit wide */ + if (status & SONIC_INT_FAE) + lp->stats.rx_frame_errors += 65536; + if (status & SONIC_INT_CRC) + lp->stats.rx_crc_errors += 65536; + if (status & SONIC_INT_MP) + lp->stats.rx_missed_errors += 65536; + + /* transmit error */ + if (status & SONIC_INT_TXER) + lp->stats.tx_errors++; + + /* + * clear interrupt bits and return + */ + SONIC_WRITE(SONIC_ISR,status); + dev->interrupt = 0; + return; +} + +/* + * We have a good packet(s), get it/them out of the buffers. + */ +static void +sonic_rx(struct device *dev) +{ + unsigned int base_addr = dev->base_addr; + struct sonic_local *lp = (struct sonic_local *)dev->priv; + int entry = lp->cur_rx & SONIC_RDS_MASK; + int status; + + while(lp->rda[entry].in_use == 0) + { + struct sk_buff *skb; + int pkt_len; + unsigned char *pkt_ptr; + + status = lp->rda[entry].rx_status; + if (sonic_debug > 3) + printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra); + if (status & SONIC_RCR_PRX) { + pkt_len = lp->rda[entry].rx_pktlen; + pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) + + lp->rda[entry].rx_pktptr_l)); + + if (sonic_debug > 3) + printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba, + lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l, + lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l, + SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0)); + + /* Malloc up new buffer. */ + skb = dev_alloc_skb(pkt_len+2); + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + lp->stats.rx_dropped++; + break; + } + skb->dev = dev; + skb_reserve(skb,2); /* 16 byte align */ + skb_put(skb,pkt_len); /* Make room */ + eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); /* pass the packet to upper layers */ + lp->stats.rx_packets++; + + } else { + /* This should only happen, if we enable accepting broken packets. */ + lp->stats.rx_errors++; + if (status & SONIC_RCR_FAER) lp->stats.rx_frame_errors++; + if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++; + } + + lp->rda[entry].in_use = 1; + entry = (++lp->cur_rx) & SONIC_RDS_MASK; + /* now give back the buffer to the receive buffer area */ + if (status & SONIC_RCR_LPKT) { + /* + * this was the last packet out of the current receice buffer + * give the buffer back to the SONIC + */ + SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff); + } + } + + /* If any worth-while packets have been received, dev_rint() + has done a mark_bh(NET_BH) for us and will work on them + when we get to the bottom-half routine. */ + return; +} + + +/* + * Get the current statistics. + * This may be called with the device open or closed. + */ +static struct enet_statistics * +sonic_get_stats(struct device *dev) +{ + struct sonic_local *lp = (struct sonic_local *)dev->priv; + unsigned int base_addr = dev->base_addr; + + /* read the tally counter from the SONIC and reset them */ + lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT); + SONIC_WRITE(SONIC_CRCT,0xffff); + lp->stats.rx_frame_errors += SONIC_READ(SONIC_FAET); + SONIC_WRITE(SONIC_FAET,0xffff); + lp->stats.rx_missed_errors += SONIC_READ(SONIC_MPT); + SONIC_WRITE(SONIC_MPT,0xffff); + + return &lp->stats; +} + + +/* + * Set or clear the multicast filter for this adaptor. + */ +static void +sonic_multicast_list(struct device *dev) +{ + struct sonic_local *lp = (struct sonic_local *)dev->priv; + unsigned int base_addr = dev->base_addr; + unsigned int rcr; + struct dev_mc_list *dmi = dev->mc_list; + unsigned char *addr; + int i; + + rcr = SONIC_READ(SONIC_RCR) & ~(SONIC_RCR_PRO | SONIC_RCR_AMC); + rcr |= SONIC_RCR_BRD; /* accept broadcast packets */ + + if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ + rcr |= SONIC_RCR_PRO; + } else { + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) { + rcr |= SONIC_RCR_AMC; + } else { + if (sonic_debug > 2) + printk ("sonic_multicast_list: mc_count %d\n",dev->mc_count); + lp->cda.cam_enable = 1; /* always enable our own address */ + for (i = 1; i <= dev->mc_count; i++) { + addr = dmi->dmi_addr; + dmi = dmi->next; + lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0]; + lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2]; + lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4]; + lp->cda.cam_enable |= (1 << i); + } + /* number of CAM entries to load */ + SONIC_WRITE(SONIC_CDC,dev->mc_count+1); + /* issue Load CAM command */ + SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); + SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); + } + } + + if (sonic_debug > 2) + printk("sonic_multicast_list: setting RCR=%x\n",rcr); + + SONIC_WRITE(SONIC_RCR,rcr); +} + + +/* + * Initialize the SONIC ethernet controller. + */ +static int sonic_init(struct device *dev) +{ + unsigned int base_addr = dev->base_addr; + unsigned int cmd; + struct sonic_local *lp = (struct sonic_local *)dev->priv; + unsigned int rra_start; + unsigned int rra_end; + int i; + + /* + * put the Sonic into software-reset mode and + * disable all interrupts + */ + SONIC_WRITE(SONIC_ISR,0x7fff); + SONIC_WRITE(SONIC_IMR,0); + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + + /* + * clear software reset flag, disable receiver, clear and + * enable interrupts, then completely initialize the SONIC + */ + SONIC_WRITE(SONIC_CMD,0); + SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS); + + + /* + * initialize the receive resource area + */ + if (sonic_debug > 2) + printk ("sonic_init: initialize receive resource area\n"); + + rra_start = lp->rra_laddr & 0xffff; + rra_end = (rra_start + (SONIC_NUM_RRS * sizeof(sonic_rr_t))) & 0xffff; + + for (i = 0; i < SONIC_NUM_RRS; i++) { + lp->rra[i].rx_bufadr_l = (lp->rba_laddr + i * SONIC_RBSIZE) & 0xffff; + lp->rra[i].rx_bufadr_h = (lp->rba_laddr + i * SONIC_RBSIZE) >> 16; + lp->rra[i].rx_bufsize_l = SONIC_RBSIZE >> 1; + lp->rra[i].rx_bufsize_h = 0; + } + + /* initialize all RRA registers */ + SONIC_WRITE(SONIC_RSA,rra_start); + SONIC_WRITE(SONIC_REA,rra_end); + SONIC_WRITE(SONIC_RRP,rra_start); + SONIC_WRITE(SONIC_RWP,rra_end); + SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16); + SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1); + + lp->cur_rra = SONIC_NUM_RRS - 2; + + /* load the resource pointers */ + if (sonic_debug > 3) + printk("sonic_init: issueing RRRA command\n"); + + SONIC_WRITE(SONIC_CMD,SONIC_CR_RRRA); + i = 0; + while (i++ < 100) { + if (SONIC_READ(SONIC_CMD) & SONIC_CR_RRRA) + break; + } + + if (sonic_debug > 2) + printk("sonic_init: status=%x\n",SONIC_READ(SONIC_CMD)); + + /* + * Initialize the receive descriptors so that they + * become a circular linked list, ie. let the last + * descriptor point to the first again. + */ + if (sonic_debug > 2) + printk ("sonic_init: initialize receive descriptors\n"); + for (i=0; irda[i].rx_status = 0; + lp->rda[i].rx_pktlen = 0; + lp->rda[i].rx_pktptr_l = 0; + lp->rda[i].rx_pktptr_h = 0; + lp->rda[i].rx_seqno = 0; + lp->rda[i].in_use = 1; + lp->rda[i].link = lp->rda_laddr + (i+1) * sizeof (sonic_rd_t); + } + /* fix last descriptor */ + lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr; + lp->cur_rx = 0; + + SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16); + SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff); + + /* + * initialize transmit descriptors + */ + if (sonic_debug > 2) + printk ("sonic_init: initialize transmit descriptors\n"); + for (i = 0; i < SONIC_NUM_TDS; i++) { + lp->tda[i].tx_status = 0; + lp->tda[i].tx_config = 0; + lp->tda[i].tx_pktsize = 0; + lp->tda[i].tx_frag_count = 0; + lp->tda[i].link = (lp->tda_laddr + (i+1) * sizeof (sonic_td_t)) | SONIC_END_OF_LINKS; + } + lp->tda[SONIC_NUM_TDS-1].link = (lp->tda_laddr & 0xffff) | SONIC_END_OF_LINKS; + + SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16); + SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff); + + /* + * put our own address to CAM desc[0] + */ + lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0]; + lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2]; + lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4]; + lp->cda.cam_enable = 1; + + for (i=0; i < 16; i++) + lp->cda.cam_desc[i].cam_entry_pointer = i; + + /* + * initialize CAM registers + */ + SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); + SONIC_WRITE(SONIC_CDC,1); + + /* + * load the CAM + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); + + i = 0; + while (i++ < 100) { + if (SONIC_READ(SONIC_ISR) & SONIC_INT_LCD) + break; + } + if (sonic_debug > 2) { + printk("sonic_init: CMD=%x, ISR=%x\n", + SONIC_READ(SONIC_CMD), + SONIC_READ(SONIC_ISR)); + } + + /* + * enable receiver, disable loopback + * and enable all interrupts + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_RXEN | SONIC_CR_STP); + SONIC_WRITE(SONIC_RCR,SONIC_RCR_DEFAULT); + SONIC_WRITE(SONIC_TCR,SONIC_TCR_DEFAULT); + SONIC_WRITE(SONIC_ISR,0x7fff); + SONIC_WRITE(SONIC_IMR,SONIC_IMR_DEFAULT); + + cmd = SONIC_READ(SONIC_CMD); + if ((cmd & SONIC_CR_RXEN) == 0 || + (cmd & SONIC_CR_STP) == 0) + printk("sonic_init: failed, status=%x\n",cmd); + + if (sonic_debug > 2) + printk("sonic_init: new status=%x\n",SONIC_READ(SONIC_CMD)); + + return(0); +} + + +/* + * Local variables: + * compile-command: "mipsel-linux-gcc -D__KERNEL__ -D__mips64 -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -mcpu=r4000 -c sonic.c" + * version-control: t + * kept-new-versions: 5 + * tab-width: 4 + * End: + */ diff -u --recursive --new-file v2.1.43/linux/drivers/net/sonic.h linux/drivers/net/sonic.h --- v2.1.43/linux/drivers/net/sonic.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/sonic.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,326 @@ +/* + * Helpfile for sonic.c + * + * (C) Waldorf Electronics, Germany + * Written by Andreas Busse + * + * NOTE: most of the structure definitions here are endian dependent. + * If you want to use this driver on big endian machines, the data + * and pad structure members must be exchanged. Also, the structures + * need to be changed accordingly to the bus size. + * + */ + +#ifndef SONIC_H +#define SONIC_H + +/* + * Macros to access SONIC registers + */ +#define SONIC_READ(reg) \ + *((volatile unsigned int *)base_addr+reg) + +#define SONIC_WRITE(reg,val) \ + *((volatile unsigned int *)base_addr+reg) = val + + +/* + * SONIC register offsets + */ + +#define SONIC_CMD 0x00 +#define SONIC_DCR 0x01 +#define SONIC_RCR 0x02 +#define SONIC_TCR 0x03 +#define SONIC_IMR 0x04 +#define SONIC_ISR 0x05 + +#define SONIC_UTDA 0x06 +#define SONIC_CTDA 0x07 + +#define SONIC_URDA 0x0d +#define SONIC_CRDA 0x0e +#define SONIC_EOBC 0x13 +#define SONIC_URRA 0x14 +#define SONIC_RSA 0x15 +#define SONIC_REA 0x16 +#define SONIC_RRP 0x17 +#define SONIC_RWP 0x18 +#define SONIC_RSC 0x2b + +#define SONIC_CEP 0x21 +#define SONIC_CAP2 0x22 +#define SONIC_CAP1 0x23 +#define SONIC_CAP0 0x24 +#define SONIC_CE 0x25 +#define SONIC_CDP 0x26 +#define SONIC_CDC 0x27 + +#define SONIC_WT0 0x29 +#define SONIC_WT1 0x2a + +#define SONIC_SR 0x28 + + +/* test-only registers */ + +#define SONIC_TPS 0x08 +#define SONIC_TFC 0x09 +#define SONIC_TSA0 0x0a +#define SONIC_TSA1 0x0b +#define SONIC_TFS 0x0c + +#define SONIC_CRBA0 0x0f +#define SONIC_CRBA1 0x10 +#define SONIC_RBWC0 0x11 +#define SONIC_RBWC1 0x12 +#define SONIC_TTDA 0x20 +#define SONIC_MDT 0x2f + +#define SONIC_TRBA0 0x19 +#define SONIC_TRBA1 0x1a +#define SONIC_TBWC0 0x1b +#define SONIC_TBWC1 0x1c +#define SONIC_LLFA 0x1f + +#define SONIC_ADDR0 0x1d +#define SONIC_ADDR1 0x1e + +/* + * Error counters + */ +#define SONIC_CRCT 0x2c +#define SONIC_FAET 0x2d +#define SONIC_MPT 0x2e + + +/* + * SONIC command bits + */ + +#define SONIC_CR_LCAM 0x0200 +#define SONIC_CR_RRRA 0x0100 +#define SONIC_CR_RST 0x0080 +#define SONIC_CR_ST 0x0020 +#define SONIC_CR_STP 0x0010 +#define SONIC_CR_RXEN 0x0008 +#define SONIC_CR_RXDIS 0x0004 +#define SONIC_CR_TXP 0x0002 +#define SONIC_CR_HTX 0x0001 + +/* + * SONIC data configuration bits + */ + +#define SONIC_DCR_EXBUS 0x8000 +#define SONIC_DCR_LBR 0x2000 +#define SONIC_DCR_PO1 0x1000 +#define SONIC_DCR_PO0 0x0800 +#define SONIC_DCR_SBUS 0x0400 +#define SONIC_DCR_USR1 0x0200 +#define SONIC_DCR_USR0 0x0100 +#define SONIC_DCR_WC1 0x0080 +#define SONIC_DCR_WC0 0x0040 +#define SONIC_DCR_DW 0x0020 +#define SONIC_DCR_BMS 0x0010 +#define SONIC_DCR_RFT1 0x0008 +#define SONIC_DCR_RFT0 0x0004 +#define SONIC_DCR_TFT1 0x0002 +#define SONIC_DCR_TFT0 0x0001 + +/* + * Constants for the SONIC receive control register. + */ + +#define SONIC_RCR_ERR 0x8000 +#define SONIC_RCR_RNT 0x4000 +#define SONIC_RCR_BRD 0x2000 +#define SONIC_RCR_PRO 0x1000 +#define SONIC_RCR_AMC 0x0800 +#define SONIC_RCR_LB1 0x0400 +#define SONIC_RCR_LB0 0x0200 + +#define SONIC_RCR_MC 0x0100 +#define SONIC_RCR_BC 0x0080 +#define SONIC_RCR_LPKT 0x0040 +#define SONIC_RCR_CRS 0x0020 +#define SONIC_RCR_COL 0x0010 +#define SONIC_RCR_CRCR 0x0008 +#define SONIC_RCR_FAER 0x0004 +#define SONIC_RCR_LBK 0x0002 +#define SONIC_RCR_PRX 0x0001 + +#define SONIC_RCR_LB_OFF 0 +#define SONIC_RCR_LB_MAC SONIC_RCR_LB0 +#define SONIC_RCR_LB_ENDEC SONIC_RCR_LB1 +#define SONIC_RCR_LB_TRANS (SONIC_RCR_LB0 | SONIC_RCR_LB1) + +/* default RCR setup */ + +#define SONIC_RCR_DEFAULT (SONIC_RCR_BRD) + + +/* + * SONIC Transmit Control register bits + */ + +#define SONIC_TCR_PINTR 0x8000 +#define SONIC_TCR_POWC 0x4000 +#define SONIC_TCR_CRCI 0x2000 +#define SONIC_TCR_EXDIS 0x1000 +#define SONIC_TCR_EXD 0x0400 +#define SONIC_TCR_DEF 0x0200 +#define SONIC_TCR_NCRS 0x0100 +#define SONIC_TCR_CRLS 0x0080 +#define SONIC_TCR_EXC 0x0040 +#define SONIC_TCR_PMB 0x0008 +#define SONIC_TCR_FU 0x0004 +#define SONIC_TCR_BCM 0x0002 +#define SONIC_TCR_PTX 0x0001 + +#define SONIC_TCR_DEFAULT 0x0000 + +/* + * Constants for the SONIC_INTERRUPT_MASK and + * SONIC_INTERRUPT_STATUS registers. + */ + +#define SONIC_INT_BR 0x4000 +#define SONIC_INT_HBL 0x2000 +#define SONIC_INT_LCD 0x1000 +#define SONIC_INT_PINT 0x0800 +#define SONIC_INT_PKTRX 0x0400 +#define SONIC_INT_TXDN 0x0200 +#define SONIC_INT_TXER 0x0100 +#define SONIC_INT_TC 0x0080 +#define SONIC_INT_RDE 0x0040 +#define SONIC_INT_RBE 0x0020 +#define SONIC_INT_RBAE 0x0010 +#define SONIC_INT_CRC 0x0008 +#define SONIC_INT_FAE 0x0004 +#define SONIC_INT_MP 0x0002 +#define SONIC_INT_RFO 0x0001 + + +/* + * The interrupts we allow. + */ + +#define SONIC_IMR_DEFAULT (SONIC_INT_BR | \ + SONIC_INT_LCD | \ + SONIC_INT_PINT | \ + SONIC_INT_PKTRX | \ + SONIC_INT_TXDN | \ + SONIC_INT_TXER | \ + SONIC_INT_RDE | \ + SONIC_INT_RBE | \ + SONIC_INT_RBAE | \ + SONIC_INT_CRC | \ + SONIC_INT_FAE | \ + SONIC_INT_MP) + + +#define SONIC_END_OF_LINKS 0x0001 + + +/* + * structure definitions + */ + +typedef struct { + u32 rx_bufadr_l; /* receive buffer ptr */ + u32 rx_bufadr_h; + + u32 rx_bufsize_l; /* no. of words in the receive buffer */ + u32 rx_bufsize_h; +} sonic_rr_t; + +/* + * Sonic receive descriptor. Receive descriptors are + * kept in a linked list of these structures. + */ + +typedef struct { + u16 rx_status; /* status after reception of a packet */ + u16 pad0; + u16 rx_pktlen; /* length of the packet incl. CRC */ + u16 pad1; + + /* + * Pointers to the location in the receive buffer area (RBA) + * where the packet resides. A packet is always received into + * a contiguous piece of memory. + */ + u16 rx_pktptr_l; + u16 pad2; + u16 rx_pktptr_h; + u16 pad3; + + u16 rx_seqno; /* sequence no. */ + u16 pad4; + + u16 link; /* link to next RDD (end if EOL bit set) */ + u16 pad5; + + /* + * Owner of this descriptor, 0= driver, 1=sonic + */ + + u16 in_use; + u16 pad6; + + caddr_t rda_next; /* pointer to next RD */ +} sonic_rd_t; + + +/* + * Describes a Transmit Descriptor + */ +typedef struct { + u16 tx_status; /* status after transmission of a packet */ + u16 pad0; + u16 tx_config; /* transmit configuration for this packet */ + u16 pad1; + u16 tx_pktsize; /* size of the packet to be transmitted */ + u16 pad2; + u16 tx_frag_count; /* no. of fragments */ + u16 pad3; + + u16 tx_frag_ptr_l; + u16 pad4; + u16 tx_frag_ptr_h; + u16 pad5; + u16 tx_frag_size; + u16 pad6; + + u16 link; /* ptr to next descriptor */ + u16 pad7; +} sonic_td_t; + + +/* + * Describes an entry in the CAM Descriptor Area. + */ + +typedef struct { + u16 cam_entry_pointer; + u16 pad; + u16 cam_frag2; + u16 pad2; + u16 cam_frag1; + u16 pad1; + u16 cam_frag0; + u16 pad0; +} sonic_cd_t; + +#define CAM_DESCRIPTORS 16 + + +typedef struct { + sonic_cd_t cam_desc[CAM_DESCRIPTORS]; + u16 cam_enable; + u16 pad; +} sonic_cda_t; + + +#endif /* SONIC_H */ diff -u --recursive --new-file v2.1.43/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.43/linux/drivers/pci/pci.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/pci/pci.c Thu Jun 26 12:33:39 1997 @@ -204,7 +204,7 @@ DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo VP-1"), DEVICE( VIA, VIA_82C576, "VT 82C576 3V"), DEVICE( VIA, VIA_82C585, "VT 82C585VP Apollo VP-1"), - DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo VP-1"), + DEVICE( VIA, VIA_82C586, "VT 82C586 Apollo VP-1"), DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c --- v2.1.43/linux/drivers/sbus/char/bwtwo.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/bwtwo.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: bwtwo.c,v 1.16 1997/06/04 08:27:26 davem Exp $ +/* $Id: bwtwo.c,v 1.17 1997/06/06 10:56:28 jj Exp $ * bwtwo.c: bwtwo console driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -74,7 +74,8 @@ bwtwo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, long base, fbinfo_t *fb) { - uint size, map_offset, r; + uint size, r; + unsigned long map_offset; int map_size; map_size = size = vma->vm_end - vma->vm_start; diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgfourteen.c linux/drivers/sbus/char/cgfourteen.c --- v2.1.43/linux/drivers/sbus/char/cgfourteen.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/cgfourteen.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: cgfourteen.c,v 1.22 1997/06/04 08:27:27 davem Exp $ +/* $Id: cgfourteen.c,v 1.23 1997/06/06 10:56:29 jj Exp $ * cgfourteen.c: Sun SparcStation console support. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -166,7 +166,7 @@ struct vm_area_struct *vma, long base, fbinfo_t *fb) { uint size, page, r, map_size; - uint map_offset = 0; + unsigned long map_offset = 0; uint ram_size = fb->info.cg14.ramsize; printk ("RAMSIZE=%d\n", ram_size); diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgsix.c linux/drivers/sbus/char/cgsix.c --- v2.1.43/linux/drivers/sbus/char/cgsix.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/cgsix.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: cgsix.c,v 1.30 1997/06/04 08:27:28 davem Exp $ +/* $Id: cgsix.c,v 1.32 1997/06/14 15:26:08 davem Exp $ * cgsix.c: cgsix frame buffer driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -233,7 +233,7 @@ long base, fbinfo_t *fb) { uint size, page, r, map_size; - uint map_offset = 0; + unsigned long map_offset = 0; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) @@ -247,7 +247,7 @@ switch (vma->vm_offset+page){ case CG6_TEC: map_size = PAGE_SIZE; - map_offset = get_phys ((unsigned long)fb->info.cg6.tec); + map_offset = get_phys ((unsigned long)fb->info.cg6.tec) & PAGE_MASK; break; case CG6_FBC: map_size = PAGE_SIZE; @@ -259,18 +259,25 @@ break; case CG6_THC: map_size = PAGE_SIZE; - map_offset = get_phys ((unsigned long)fb->info.cg6.thc); + map_offset = get_phys ((unsigned long)fb->info.cg6.thc) & PAGE_MASK; break; case CG6_BTREGS: map_size = PAGE_SIZE; map_offset = get_phys ((unsigned long)fb->info.cg6.bt); break; + + /* For Ultra, make sure the following two are right. + * The above two happen to work out (for example FBC and + * TEC will get mapped by one I/O page mapping because + * of the 8192 byte page size, same for FHC/THC. -DaveM + */ + case CG6_DHC: - map_size = PAGE_SIZE * 40; + map_size = /* PAGE_SIZE * 40 */ (4096 * 40); map_offset = get_phys ((unsigned long)fb->info.cg6.dhc); break; case CG6_ROM: - map_size = PAGE_SIZE * 16; + map_size = /* PAGE_SIZE * 16 */ (4096 * 16); map_offset = get_phys ((unsigned long)fb->info.cg6.rom); break; case CG6_RAM: @@ -449,14 +456,22 @@ sizeof (struct bt_regs), "cgsix_dac", cg6_io, 0); cg6info->fhc = sparc_alloc_io (cg6+CG6_FHC_OFFSET, 0, sizeof (int), "cgsix_fhc", cg6_io, 0); +#if PAGE_SHIFT <= 12 cg6info->thc = sparc_alloc_io (cg6+CG6_THC_OFFSET, 0, sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0); +#else + cg6info->thc = (struct cg6_thc *)(((char *)cg6info->fhc)+0x1000); +#endif + cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0, + 0x1000, "cgsix_fbc", cg6_io, 0); +#if PAGE_SHIFT <= 12 cg6info->tec = sparc_alloc_io (cg6+CG6_TEC_OFFSET, 0, sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0); +#else + cg6info->tec = (struct cg6_tec *)(((char *)cg6info->fbc)+0x1000); +#endif cg6info->dhc = sparc_alloc_io (cg6+CG6_DHC_OFFSET, 0, 0x40000, "cgsix_dhc", cg6_io, 0); - cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0, - 0x1000, "cgsix_fbc", cg6_io, 0); cg6info->rom = sparc_alloc_io (cg6+CG6_ROM_OFFSET, 0, 0x10000, "cgsix_rom", cg6_io, 0); if (!fb->base) { diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgthree.c linux/drivers/sbus/char/cgthree.c --- v2.1.43/linux/drivers/sbus/char/cgthree.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/cgthree.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: cgthree.c,v 1.21 1997/06/04 08:27:29 davem Exp $ +/* $Id: cgthree.c,v 1.22 1997/06/06 10:56:30 jj Exp $ * cgtree.c: cg3 frame buffer driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -96,7 +96,7 @@ long base, fbinfo_t *fb) { uint size, page, r, map_size; - uint map_offset = 0; + unsigned long map_offset = 0; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/fb.h linux/drivers/sbus/char/fb.h --- v2.1.43/linux/drivers/sbus/char/fb.h Wed Apr 23 19:01:21 1997 +++ linux/drivers/sbus/char/fb.h Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: fb.h,v 1.26 1997/04/17 02:29:33 miguel Exp $ +/* $Id: fb.h,v 1.27 1997/06/06 10:56:28 jj Exp $ * fb.h: contains the definitions of the structures that various sun * frame buffer can use to do console driver stuff. * @@ -183,7 +183,7 @@ extern int ints_per_line; /* used in the mmap routines */ -extern unsigned int get_phys (unsigned long addr); +extern unsigned long get_phys (unsigned long addr); extern int get_iospace (unsigned long addr); extern void render_screen(void); diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/leo.c linux/drivers/sbus/char/leo.c --- v2.1.43/linux/drivers/sbus/char/leo.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/leo.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: leo.c,v 1.18 1997/06/04 08:27:30 davem Exp $ +/* $Id: leo.c,v 1.19 1997/06/06 10:56:30 jj Exp $ * leo.c: SUNW,leo 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -143,7 +143,7 @@ long base, fbinfo_t *fb) { uint size, page, r, map_size = 0; - uint map_offset = 0; + unsigned long map_offset = 0; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/suncons.c linux/drivers/sbus/char/suncons.c --- v2.1.43/linux/drivers/sbus/char/suncons.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/suncons.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: suncons.c,v 1.63 1997/05/31 18:33:25 mj Exp $ +/* $Id: suncons.c,v 1.64 1997/06/06 10:56:25 jj Exp $ * * suncons.c: Sun SparcStation console support. * @@ -759,7 +759,7 @@ (*fb_restore_palette) (&fbinfo[0]); } -unsigned int +unsigned long get_phys (unsigned long addr) { return __get_phys(addr); @@ -1641,51 +1641,55 @@ int sun_hw_scursor (struct fbcursor *cursor, fbinfo_t *fb) { - int op = cursor->set; + int op; int i, bytes = 0; + struct fbcursor f; + char red[2], green[2], blue[2]; + if (copy_from_user (&f, cursor, sizeof(struct fbcursor))) + return -EFAULT; + op = f.set; if (op & FB_CUR_SETSHAPE){ - if ((uint) cursor->size.fbx > fb->cursor.hwsize.fbx) + if ((uint) f.size.fbx > fb->cursor.hwsize.fbx) return -EINVAL; - if ((uint) cursor->size.fby > fb->cursor.hwsize.fby) + if ((uint) f.size.fby > fb->cursor.hwsize.fby) return -EINVAL; - bytes = (cursor->size.fby * 32)/8; - i = verify_area (VERIFY_READ, cursor->image, bytes); + bytes = (f.size.fby * 32)/8; + i = verify_area (VERIFY_READ, f.image, bytes); if (i) return i; - i = verify_area (VERIFY_READ, cursor->mask, bytes); + i = verify_area (VERIFY_READ, f.mask, bytes); if (i) return i; } if (op & FB_CUR_SETCMAP){ - if (cursor->cmap.index && cursor->cmap.count != 2) + if (f.cmap.index || f.cmap.count != 2) return -EINVAL; - i = verify_area (VERIFY_READ, cursor->cmap.red, 2); - if (i) return i; - i = verify_area (VERIFY_READ, cursor->cmap.green, 2); - if (i) return i; - i = verify_area (VERIFY_READ, cursor->cmap.blue, 2); - if (i) return i; + if (copy_from_user (red, f.cmap.red, 2) || + copy_from_user (green, f.cmap.green, 2) || + copy_from_user (blue, f.cmap.blue, 2)) + return -EFAULT; } if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){ if (op & FB_CUR_SETCUR) - fb->cursor.enable = cursor->enable; + fb->cursor.enable = f.enable; if (op & FB_CUR_SETPOS) - fb->cursor.cpos = cursor->pos; + fb->cursor.cpos = f.pos; if (op & FB_CUR_SETHOT) - fb->cursor.chot = cursor->hot; + fb->cursor.chot = f.hot; (*fb->setcursor) (fb); } if (op & FB_CUR_SETCMAP) - (*fb->setcursormap) (fb, cursor->cmap.red, cursor->cmap.green, cursor->cmap.blue); + (*fb->setcursormap) (fb, red, green, blue); if (op & FB_CUR_SETSHAPE){ uint u; - fb->cursor.size = cursor->size; + fb->cursor.size = f.size; memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits)); - memcpy (fb->cursor.bits [0], cursor->mask, bytes); - memcpy (fb->cursor.bits [1], cursor->image, bytes); + if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) || + copy_from_user (fb->cursor.bits [1], f.image, bytes)) + return -EFAULT; u = ~0; - if (cursor->size.fbx < fb->cursor.hwsize.fbx) - u = ~(u >> cursor->size.fbx); + if (f.size.fbx < fb->cursor.hwsize.fbx) + u = ~(u >> f.size.fbx); for (i = fb->cursor.size.fby - 1; i >= 0; i--) { fb->cursor.bits [0][i] &= u; fb->cursor.bits [1][i] &= fb->cursor.bits [0][i]; diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/sunfb.c linux/drivers/sbus/char/sunfb.c --- v2.1.43/linux/drivers/sbus/char/sunfb.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/sunfb.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: sunfb.c,v 1.23 1997/05/31 18:33:26 mj Exp $ +/* $Id: sunfb.c,v 1.24 1997/06/06 10:56:24 jj Exp $ * sunfb.c: Sun generic frame buffer support. * * Copyright (C) 1995, 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -132,7 +132,7 @@ if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) - count = 256 - cmap->index; + count = 256 - index; __get_user_ret(rp, &cmap->red, -EFAULT); __get_user_ret(gp, &cmap->green, -EFAULT); __get_user_ret(bp, &cmap->blue, -EFAULT); @@ -146,7 +146,7 @@ __put_user_ret(fb->color_map CM(i,2), bp, -EFAULT); rp++; gp++; bp++; } - (*fb->loadcmap)(fb, cmap->index, count); + (*fb->loadcmap)(fb, index, count); break; } @@ -164,13 +164,13 @@ if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) - count = 256 - cmap->index; + count = 256 - index; __get_user_ret(rp, &cmap->red, -EFAULT); __get_user_ret(gp, &cmap->green, -EFAULT); __get_user_ret(bp, &cmap->blue, -EFAULT); - if(verify_area (VERIFY_READ, rp, cmap->count)) return -EFAULT; - if(verify_area (VERIFY_READ, gp, cmap->count)) return -EFAULT; - if(verify_area (VERIFY_READ, bp, cmap->count)) return -EFAULT; + if(verify_area (VERIFY_READ, rp, count)) return -EFAULT; + if(verify_area (VERIFY_READ, gp, count)) return -EFAULT; + if(verify_area (VERIFY_READ, bp, count)) return -EFAULT; end = index + count; for (i = index; i < end; i++){ @@ -179,7 +179,7 @@ __get_user_ret(fb->color_map CM(i,2), bp, -EFAULT); rp++; gp++; bp++; } - (*fb->loadcmap)(fb, cmap->index, count); + (*fb->loadcmap)(fb, index, count); break; } diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/tcx.c linux/drivers/sbus/char/tcx.c --- v2.1.43/linux/drivers/sbus/char/tcx.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/tcx.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: tcx.c,v 1.15 1997/06/04 08:27:32 davem Exp $ +/* $Id: tcx.c,v 1.16 1997/06/06 10:56:31 jj Exp $ * tcx.c: SUNW,tcx 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -110,7 +110,8 @@ long base, fbinfo_t *fb) { uint size, page, r, map_size; - uint map_offset = 0, i; + unsigned long map_offset = 0; + uint i; long offsets[13] = { -1, TCX_RAM24BIT, TCX_UNK3, TCX_UNK4, -1, TCX_UNK6, TCX_UNK7, -1, -1, -1, TCX_UNK2, TCX_DHC, TCX_ALT }; diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/weitek.c linux/drivers/sbus/char/weitek.c --- v2.1.43/linux/drivers/sbus/char/weitek.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/sbus/char/weitek.c Thu Jun 26 12:33:39 1997 @@ -1,4 +1,4 @@ -/* $Id: weitek.c,v 1.12 1997/06/04 08:27:34 davem Exp $ +/* $Id: weitek.c,v 1.13 1997/06/06 10:56:31 jj Exp $ * weitek.c: Tadpole P9100/P9000 console driver * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) @@ -41,7 +41,7 @@ long base, fbinfo_t *fb) { unsigned int size, page, r, map_size; - unsigned int map_offset = 0; + unsigned long map_offset = 0; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) diff -u --recursive --new-file v2.1.43/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.43/linux/fs/affs/namei.c Mon Jun 16 16:35:56 1997 +++ linux/fs/affs/namei.c Thu Jul 3 17:30:26 1997 @@ -566,12 +566,12 @@ old_bh = affs_find_entry(old_dir,old_name,old_len,&old_ino); if (!old_bh) goto end_rename; - old_inode = __iget(old_dir->i_sb,old_ino,0); + old_inode = __iget(old_dir->i_sb,old_ino); if (!old_inode) goto end_rename; new_bh = affs_find_entry(new_dir,new_name,new_len,&new_ino); if (new_bh) { - new_inode = __iget(new_dir->i_sb,new_ino,0); + new_inode = __iget(new_dir->i_sb,new_ino); if (!new_inode) { /* What does this mean? */ affs_brelse(new_bh); new_bh = NULL; diff -u --recursive --new-file v2.1.43/linux/fs/autofs/init.c linux/fs/autofs/init.c --- v2.1.43/linux/fs/autofs/init.c Mon Jun 16 16:35:56 1997 +++ linux/fs/autofs/init.c Thu Jun 26 12:33:39 1997 @@ -21,7 +21,7 @@ static struct file_system_type autofs_fs_type = { "autofs", - FS_NO_DCACHE, + 0 /* FS_NO_DCACHE doesn't work correctly */, autofs_read_super, NULL }; diff -u --recursive --new-file v2.1.43/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c --- v2.1.43/linux/fs/binfmt_misc.c Mon Jun 16 16:35:57 1997 +++ linux/fs/binfmt_misc.c Tue Jul 1 08:55:56 1997 @@ -7,9 +7,11 @@ * a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and * binfmt_mz. * - * 25.4.97 first version - * [...] - * 19.5.97 cleanup + * 1997-04-25 first version + * [...] + * 1997-05-19 cleanup + * 1997-06-26 hpa: pass the real filename rather than argv[0] + * 1997-06-30 minor cleanup */ #include @@ -85,7 +87,6 @@ *ep = e->next; entry_proc_cleanup(e); kfree(e); - MOD_DEC_USE_COUNT; } write_unlock(&entries_lock); } @@ -102,7 +103,6 @@ entries = entries->next; entry_proc_cleanup(e); kfree(e); - MOD_DEC_USE_COUNT; } write_unlock(&entries_lock); } @@ -161,7 +161,6 @@ char *iname_addr = iname, *p; int retval, fmt_flags = 0; - MOD_INC_USE_COUNT; if (!enabled) { retval = -ENOEXEC; goto _ret; @@ -185,12 +184,11 @@ /* Build args for interpreter */ if ((fmt_flags & ENTRY_STRIP_EXT) && - (p = strrchr(bprm->filename, '.'))) { + (p = strrchr(bprm->filename, '.'))) *p = '\0'; - remove_arg_zero(bprm); - bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2); - bprm->argc++; - } + remove_arg_zero(bprm); + bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2); + bprm->argc++; bprm->p = copy_strings(1, &iname_addr, bprm->page, bprm->p, 2); bprm->argc++; if (!bprm->p) { @@ -206,7 +204,6 @@ if ((retval = prepare_binprm(bprm)) >= 0) retval = search_binary_handler(bprm, regs); _ret: - MOD_DEC_USE_COUNT; return retval; } @@ -265,18 +262,13 @@ struct binfmt_entry *e; int memsize, cnt = count - 1, err = 0; - MOD_INC_USE_COUNT; /* some sanity checks */ - if ((count < 11) || (count > 256)) { - err = -EINVAL; - goto _err; - } + if ((count < 11) || (count > 256)) + return -EINVAL; memsize = sizeof(struct binfmt_entry) + count; - if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER))) { - err = -ENOMEM; - goto _err; - } + if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER))) + return -ENOMEM; sp = buffer + 1; del = buffer[0]; @@ -313,8 +305,7 @@ !(e->proc_name) || !(e->interpreter) || entry_proc_setup(e)) { kfree(e); - err = -EINVAL; - goto _err; + return -EINVAL; } write_lock(&entries_lock); @@ -323,9 +314,6 @@ write_unlock(&entries_lock); return count; -_err: - MOD_DEC_USE_COUNT; - return err; } /* @@ -340,7 +328,6 @@ char *dp; int elen, i; - MOD_INC_USE_COUNT; #ifndef VERBOSE_STATUS if (data) { read_lock(&entries_lock); @@ -400,7 +387,6 @@ *eof = (elen <= count) ? 1 : 0; *start = page + off; - MOD_DEC_USE_COUNT; return elen; } @@ -414,7 +400,6 @@ struct binfmt_entry *e; int res = count; - MOD_INC_USE_COUNT; if (((buffer[0] == '1') || (buffer[0] == '0')) && ((count == 1) || ((count == 2) && (buffer[1] == '\n')))) { if (data) { @@ -434,7 +419,6 @@ } else { res = -EINVAL; } - MOD_DEC_USE_COUNT; return res; } @@ -499,6 +483,7 @@ unregister_binfmt(&misc_format); remove_proc_entry("register", bm_dir); remove_proc_entry("status", bm_dir); + clear_entries(); remove_proc_entry("sys/fs/binfmt_misc", NULL); } #endif diff -u --recursive --new-file v2.1.43/linux/fs/buffer.c linux/fs/buffer.c --- v2.1.43/linux/fs/buffer.c Mon Jun 16 16:35:57 1997 +++ linux/fs/buffer.c Tue Jul 1 20:21:42 1997 @@ -495,17 +495,18 @@ static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size) { - struct buffer_head * tmp; - - for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next) - if (tmp->b_blocknr == block && tmp->b_dev == dev) { - if (tmp->b_size == size) - return tmp; + struct buffer_head * next; - printk("VFS: Wrong blocksize on device %s\n", - kdevname(dev)); - return NULL; - } + next = hash(dev,block); + for (;;) { + struct buffer_head *tmp = next; + if (!next) + break; + next = tmp->b_next; + if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev) + continue; + return tmp; + } return NULL; } @@ -518,10 +519,11 @@ */ struct buffer_head * get_hash_table(kdev_t dev, int block, int size) { - struct buffer_head * bh; - for (;;) { - if (!(bh=find_buffer(dev,block,size))) + struct buffer_head * bh; + + bh=find_buffer(dev,block,size); + if (!bh) return NULL; bh->b_count++; wait_on_buffer(bh); @@ -1610,6 +1612,7 @@ next->b_count--; } } + run_task_queue(&tq_disk); #ifdef DEBUG if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount); printk("Wrote %d/%d buffers\n", nwritten, ndirty); diff -u --recursive --new-file v2.1.43/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.43/linux/fs/dcache.c Mon Jun 16 16:35:57 1997 +++ linux/fs/dcache.c Sat Jul 5 23:12:35 1997 @@ -65,77 +65,24 @@ * are alive. */ -#include #include #include #include #include #include +#include /* this should be removed after the beta phase */ -/* #define DEBUG */ +/*#define DEBUG*/ /*#undef DEBUG*/ -/* #define DEBUG_DDIR_COUNT */ +/*#define DEBUG_DDIR_COUNT*/ -#define D_HASHSIZE 64 - -/* local flags for d_flag */ -#define D_DIR 32 -#define D_HASHED 64 -#define D_ZOMBIE 128 -#define D_PRELIMINARY 256 -#define D_INC_DDIR 512 +void printpath(struct dentry * entry); /* local flags for d_del() */ #define D_RECURSIVE 4 #define D_NO_FREE 8 -/* adjust these constants if you know a probability distribution ... */ -#define D_SMALL 16 -#define D_MEDIUM 64 -#define D_LARGE 256 -#define D_HUGE D_MAXLEN - -#define BASE_DHEADER(x) (struct dheader*)((unsigned long)(x) & ~(PAGE_SIZE-1)) -#define BYTE_ADD(x,n) (void*)((char*)(x) + (n)) -#define BYTE_SUB(x,n) (void*)((char*)(x) - (n)) - -/* This is for global allocation of dentries. Remove this when - * converting to SLAB. - */ -struct dheader { - struct dentry * emptylist; - short free, maxfree; - struct dheader * next; - struct dheader * prev; -}; - -struct anchors { - struct dheader * free; /* each contains at least 1 empty dentry */ - struct dheader * full; /* all the used up ones */ - struct dheader * dir_free; - struct dheader * dir_full; -}; - -/* This is only used for directory dentries. Think of it as an extension - * of the dentry. - * It is defined as separate struct, so it uses up space only - * where necessary. - */ -struct ddir { - struct dentry * dd_hashtable[D_HASHSIZE]; - struct dentry * dd_neglist; - struct dentry * dd_basketlist; - struct dentry * dd_zombielist; - unsigned short dd_alloced; /* # d_alloc()ed, but not yet d_add()ed */ - unsigned short dd_hashed; /* # of entries in hashtable */ - unsigned short dd_true_hashed; /* # non-preliminaries in hashtable */ - unsigned short dd_negs; /* # of negative entries */ -}; - -DEF_INSERT(header,struct dheader,next,prev) -DEF_REMOVE(header,struct dheader,next,prev) - DEF_INSERT(alias,struct dentry,d_next,d_prev) DEF_REMOVE(alias,struct dentry,d_next,d_prev) @@ -145,13 +92,30 @@ DEF_INSERT(basket,struct dentry,d_basket_next,d_basket_prev) DEF_REMOVE(basket,struct dentry,d_basket_next,d_basket_prev) -static struct anchors anchors[4]; - struct dentry * the_root = NULL; +/* + * This is the single most critical data structure when it comes + * to the dcache: the hashtable for lookups. Somebody should try + * to make this good - I've just made it work. + * + * This hash-function tries to avoid losing too many bits of hash + * information, yet avoid using a prime hash-size or similar. + */ +#define D_HASHBITS 10 +#define D_HASHSIZE (1UL << D_HASHBITS) +#define D_HASHMASK (D_HASHSIZE-1) +struct dentry * dentry_hashtable[D_HASHSIZE]; + +static inline unsigned long dentry_hash(struct dentry *dir, int name_hash) +{ + unsigned long hash = name_hash + (unsigned long) dir; + hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2); + return hash & D_HASHMASK; +} + unsigned long name_cache_init(unsigned long mem_start, unsigned long mem_end) { - memset(anchors, 0, sizeof(anchors)); return mem_start; } @@ -174,7 +138,7 @@ if(cnt % 1000 == 0) printk("------%d allocated: %d: %d %d %d\n", inodes_stat, cnt, x_alloc, x_freed, x_free); - if(cnt>=20000) panic("stop"); + if (cnt>=20000) panic("stop"); } #if 0 @@ -182,7 +146,7 @@ { int i; for(i = cnt-1; i>=0; i--) - if(tst[i] == ptr) + if (tst[i] == ptr) return i; return -1; } @@ -195,55 +159,18 @@ void LOG(char * txt, struct dentry * entry) { static int count = 0; - if(entry) { + if (entry) { TST(txt,entry); } - if(count) { + if (count) { count--; printk("%s: entry=%p\n", txt, entry); } } #ifdef DEBUG_DDIR_COUNT -static struct ddir * d_dir(struct dentry * entry); void recursive_test(struct dentry * entry) { - int i; - struct ddir * ddir = d_dir(entry); - int sons = 0; - - if(ddir->dd_zombielist) - sons++; - for(i=0; i < D_HASHSIZE; i++) { - struct dentry ** base = &ddir->dd_hashtable[i]; - struct dentry * tmp = *base; - if(tmp) do { - TST("__clear",tmp); - if(!(tmp->d_flag & D_HASHED)) { - printk("VFS: dcache entry not hashed!\n"); - printpath(*base); printk("\n"); - printpath(tmp); - } - if(!(tmp->d_flag & D_PRELIMINARY)) - sons++; - if(tmp->d_flag & D_DIR) - recursive_test(tmp); - tmp = tmp->d_hash_next; - } while(tmp && tmp != *base); - } - if(!sons && !(entry->d_flag & D_PRELIMINARY) && entry->u.d_inode) { - struct inode * inode = entry->u.d_inode; - if(!atomic_read(&inode->i_count)) { - if(!(inode->i_status & 1/*ST_AGED*/)) { - printpath(entry); - printk(" is not aged!\n"); - } - if(inode->i_ddir_count) { - printpath(entry); - printk(" has ddir_count blockage!\n"); - } - } - } } #else #define recursive_test(e) /*nothing*/ @@ -258,22 +185,21 @@ void printpath(struct dentry * entry) { - if(!IS_ROOT(entry)) + if (!IS_ROOT(entry)) printpath(entry->d_parent); - printk("/%s", entry->d_name); + printk("/%s", entry->d_name.name); } -static inline long has_sons(struct ddir * ddir) +static inline long has_sons(struct dentry * ddir) { return ((ddir->dd_alloced | ddir->dd_hashed) || - ddir->dd_neglist || ddir->dd_basketlist || ddir->dd_zombielist); } -static inline int has_true_sons(struct ddir * ddir) +static inline int has_true_sons(struct dentry * ddir) { - return (ddir->dd_alloced | ddir->dd_true_hashed); + return (ddir->dd_alloced | ddir->dd_hashed); } /* Only hold the i_ddir_count pseudo refcount when neccessary (i.e. when @@ -281,10 +207,10 @@ */ static inline void inc_ddir(struct dentry * entry, struct inode * inode) { - if(!(entry->d_flag & D_INC_DDIR)) { + if (!(entry->d_flag & D_INC_DDIR)) { entry->d_flag |= D_INC_DDIR; #ifdef DEBUG - if(inode->i_ddir_count) { + if (inode->i_ddir_count) { printpath(entry); printk(" ddir_count=%d\n", inode->i_ddir_count); } @@ -296,106 +222,58 @@ static inline blocking void dec_ddir(struct dentry * entry, struct inode * inode) { - if(entry->d_flag & D_INC_DDIR) { + if (entry->d_flag & D_INC_DDIR) { entry->d_flag &= ~D_INC_DDIR; inode->i_ddir_count--; - if(!inode->i_ddir_count) + if (!inode->i_ddir_count) __iput(inode); } } -/* Do not inline this many times. */ -static void d_panic(void) -{ - panic("VFS: dcache directory corruption"); -} +#define NAME_ALLOC_LEN(len) ((len+16) & ~15) -static inline struct ddir * d_dir(struct dentry * entry) +struct dentry * d_alloc(struct dentry * parent, struct qstr *name, int isdir) { - struct ddir * res = BYTE_SUB(entry, sizeof(struct ddir)); - - if(!(entry->d_flag & D_DIR)) - d_panic(); -#ifdef DEBUG - if(!entry) - panic("entry NULL!"); - if(BASE_DHEADER(res) != BASE_DHEADER(entry)) - printk("Scheisse!!!\n"); -#endif - return res; -} + char *str; + struct dentry *res; + int size = sizeof(struct dentry); + int flag = 0; -static /*inline*/ struct dheader * dinit(int isdir, int size) -{ - struct dheader * res = (struct dheader*)__get_free_page(GFP_KERNEL); - int restlen = PAGE_SIZE - sizeof(struct dheader); - struct dentry * ptr = BYTE_ADD(res, sizeof(struct dheader)); + if (isdir) { + flag = D_DIR; + } + res = kmalloc(size, GFP_KERNEL); + if (!res) + return NULL; - if(!res) + str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); + if (!str) { + kfree(res); return NULL; - memset(res, 0, sizeof(struct dheader)); - if(isdir) { - ptr = BYTE_ADD(ptr, sizeof(struct ddir)); - size += sizeof(struct ddir); - } - if(BASE_DHEADER(ptr) != res) - panic("Bad kernel page alignment"); - size += sizeof(struct dentry) - D_MAXLEN; - res->emptylist = NULL; - res->free = 0; - while(restlen >= size) { -#ifdef DEBUG - ins(ptr); - if(BASE_DHEADER(ptr) != res) - panic("Wrong dinit!"); -#endif - ptr->d_next = res->emptylist; - res->emptylist = ptr; - ptr = BYTE_ADD(ptr, size); - res->free++; - restlen -= size; } - res->maxfree = res->free; - return res; -} + + memcpy(str, name->name, name->len); + str[name->len] = 0; + + memset(res, 0, size); -static /*inline*/ struct dentry * __dalloc(struct anchors * anchor, - struct dentry * parent, int isdir, - int len, int size) -{ - struct dheader ** free = isdir ? &anchor->dir_free : &anchor->free; - struct dheader ** full = isdir ? &anchor->dir_full : &anchor->full; - struct dheader * base = *free; - struct dentry * res; - - if(!base) { - base = dinit(isdir, size); - if(!base) - return NULL; - insert_header(free, base); - } - base->free--; - res = base->emptylist; - if(!(base->emptylist = res->d_next)) { - remove_header(free, base); - insert_header(full, base); - } - memset(res, 0, sizeof(struct dentry) - D_MAXLEN); - if(isdir) { - res->d_flag = D_DIR; - memset(d_dir(res), 0, sizeof(struct ddir)); - } - res->d_len = len; res->d_parent = parent; - if(parent) { - struct ddir * pdir = d_dir(parent); + res->d_mounts = res; + res->d_covers = res; + res->d_flag = flag; + + res->d_name.name = str; + res->d_name.len = name->len; + res->d_name.hash = name->hash; + + if (parent) { #ifdef DEBUG - if(pdir->dd_alloced > 1 && !IS_ROOT(parent)) { + if (parent->dd_alloced > 1 && !IS_ROOT(parent)) { printpath(parent); - printk(" dd_alloced=%d\n", pdir->dd_alloced); + printk(" dd_alloced=%d\n", parent->dd_alloced); } #endif - pdir->dd_alloced++; + parent->dd_alloced++; } #ifdef DEBUG x_alloc++; @@ -403,48 +281,19 @@ return res; } -struct dentry * d_alloc(struct dentry * parent, int len, int isdir) -{ - int i, size; - -#ifdef DEBUG - if(the_root) - recursive_test(the_root); - LOG("d_alloc", parent); -#endif - if(len >= D_MEDIUM) { - if(len >= D_LARGE) { - i = 3; - size = D_HUGE; - } else { - i = 2; - size = D_LARGE; - } - } else if(len >= D_SMALL) { - i = 1; - size = D_MEDIUM; - } else { - i = 0; - size = D_SMALL; - } - return __dalloc(&anchors[i], parent, isdir, len, size); -} - -extern blocking struct dentry * d_alloc_root(struct inode * root_inode) +extern blocking struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root) { - struct dentry * res = the_root; + struct dentry *res; + struct qstr name = { "", 0, 0 }; - if(res) { - d_del(res, D_NO_CLEAR_INODE); /* invalidate everything beyond */ + if (old_root) { + d_del(old_root, D_NO_CLEAR_INODE); /* invalidate everything beyond */ + res = old_root; } else { - struct ddir * ddir; - - the_root = res = d_alloc(NULL, 0, 1); + res = d_alloc(NULL, &name, 1); LOG("d_alloc_root", res); res->d_parent = res; - res->d_name[0]='\0'; - ddir = d_dir(res); - ddir->dd_alloced = 999; /* protect from deletion */ + res->dd_alloced = 999; /* protect from deletion */ } insert_alias(&root_inode->i_dentry, res); root_inode->i_dent_count++; @@ -453,66 +302,36 @@ return res; } -static inline unsigned long d_hash(char first, char last) -{ - return ((unsigned long)first ^ ((unsigned long)last << 4)) & (D_HASHSIZE-1); -} - -static inline struct dentry ** d_base_entry(struct ddir * pdir, struct dentry * entry) +static inline struct dentry ** d_base_qstr(struct dentry * parent, struct qstr * s) { - return &pdir->dd_hashtable[d_hash(entry->d_name[0], - entry->d_name[entry->d_len-1])]; + return dentry_hashtable + dentry_hash(parent, s->hash); } -static inline struct dentry ** d_base_qstr(struct ddir * pdir, - struct qstr * s1, - struct qstr * s2) +static inline struct dentry ** d_base_entry(struct dentry * pdir, struct dentry * entry) { - unsigned long hash; - - if(s2 && s2->len) { - hash = d_hash(s1->name[0], s2->name[s2->len-1]); - } else { - hash = d_hash(s1->name[0], s1->name[s1->len-1]); - } - return &pdir->dd_hashtable[hash]; + return d_base_qstr(pdir, &entry->d_name); } static /*inline*/ blocking void _d_remove_from_parent(struct dentry * entry, - struct ddir * pdir, + struct dentry * parent, struct inode * inode, int flags) { - if(entry->d_flag & D_HASHED) { - struct dentry ** base = d_base_entry(pdir, entry); + if (entry->d_flag & D_HASHED) { + struct dentry ** base = d_base_entry(parent, entry); remove_hash(base, entry); entry->d_flag &= ~D_HASHED; - pdir->dd_hashed--; - if(!(entry->d_flag & D_PRELIMINARY)) { - pdir->dd_true_hashed--; - if(!inode) { -#ifdef DEBUG - if(!entry->d_next || !entry->d_prev) { - printpath(entry); - printk(" flags=%x d_flag=%x negs=%d " - "hashed=%d\n", flags, entry->d_flag, - pdir->dd_negs, pdir->dd_hashed); - } -#endif - remove_alias(&pdir->dd_neglist, entry); - pdir->dd_negs--; - } - } + parent->dd_hashed--; } else if(!(entry->d_flag & D_ZOMBIE)) { #ifdef DEBUG - if(!pdir->dd_alloced) printk("dd_alloced is 0!\n"); + if (!parent->dd_alloced) printk("dd_alloced is 0!\n"); #endif - pdir->dd_alloced--; + parent->dd_alloced--; } - if(entry->d_flag & D_BASKET) { - remove_basket(&pdir->dd_basketlist, entry); + if (entry->d_flag & D_BASKET) { + remove_basket(&parent->dd_basketlist, entry); entry->d_flag &= ~D_BASKET; } } @@ -528,103 +347,68 @@ * dir is cleared, resulting also in zombies. */ static /*inline*/ void _d_handle_zombie(struct dentry * entry, - struct ddir * ddir, - struct ddir * pdir) + struct dentry * parent) { - if(entry->d_flag & D_DIR) { - if(entry->d_flag & D_ZOMBIE) { - if(!has_sons(ddir)) { + if (entry->d_flag & D_DIR) { + if (entry->d_flag & D_ZOMBIE) { + if (!has_sons(entry)) { entry->d_flag &= ~D_ZOMBIE; - remove_hash(&pdir->dd_zombielist, entry); - if(!pdir->dd_zombielist && - (entry->d_parent->d_flag & D_ZOMBIE)) { - d_del(entry->d_parent, D_NORMAL); + remove_hash(&parent->dd_zombielist, entry); + if (!parent->dd_zombielist && + (parent->d_flag & D_ZOMBIE)) { + d_del(parent, D_NORMAL); } } - } else if(has_sons(ddir)) { + } else if(has_sons(entry)) { entry->d_flag |= D_ZOMBIE; - insert_hash(&pdir->dd_zombielist, entry); - - /* This condition is no longer a bug, with the removal - * of recursive_clear() this happens naturally during - * an unmount attempt of a filesystem which is busy. - */ -#if 0 - /* Not sure when this message should show up... */ - if(!IS_ROOT(entry)) { - printk("VFS: clearing dcache directory " - "with successors\n"); -#ifdef DEBUG - printpath(entry); - printk(" d_flag=%x alloced=%d negs=%d hashed=%d " - "basket=%p zombies=%p\n", - entry->d_flag, ddir->dd_alloced, - ddir->dd_negs, ddir->dd_hashed, - ddir->dd_basketlist, ddir->dd_zombielist); -#endif - } -#endif + insert_hash(&parent->dd_zombielist, entry); } } } static /*inline*/ blocking void _d_del(struct dentry * entry, - struct anchors * anchor, int flags) { - struct dheader ** free; - struct dheader ** full; - struct dheader * base = BASE_DHEADER(entry); - struct ddir * ddir = NULL; - struct ddir * pdir; - struct inode * inode = entry->d_flag & D_PRELIMINARY ? NULL : entry->u.d_inode; + struct inode * inode = entry->u.d_inode; + struct dentry *parent; #ifdef DEBUG - if(inode) + if (inode) xcheck("_d_del", inode); #endif - if(!entry->d_parent) { + if (!entry->d_parent) { printk("VFS: dcache parent is NULL\n"); return; } - if(entry->d_flag & D_DIR) { - free = &anchor->dir_free; - full = &anchor->dir_full; - } else { - free = &anchor->free; - full = &anchor->full; - } - pdir = d_dir(entry->d_parent); - if(!IS_ROOT(entry)) - _d_remove_from_parent(entry, pdir, inode, flags); + parent = entry->d_parent; + if (!IS_ROOT(entry)) + _d_remove_from_parent(entry, parent, inode, flags); /* This may block, be careful! _d_remove_from_parent() is * thus called before. */ - if(entry->d_flag & D_DIR) - ddir = d_dir(entry); - if(IS_ROOT(entry)) + if (IS_ROOT(entry)) return; - if(flags & D_NO_FREE) { + if (flags & D_NO_FREE) { /* Make it re-d_add()able */ - pdir->dd_alloced++; + parent->dd_alloced++; entry->d_flag &= D_DIR; } else - _d_handle_zombie(entry, ddir, pdir); + _d_handle_zombie(entry, parent); /* This dec_ddir() must occur after zombie handling. */ - if(!has_true_sons(pdir)) - dec_ddir(entry->d_parent, entry->d_parent->u.d_inode); + if (!has_true_sons(parent)) + dec_ddir(parent, parent->u.d_inode); entry->u.d_inode = NULL; - if(inode) { + if (inode) { remove_alias(&inode->i_dentry, entry); inode->i_dent_count--; if (entry->d_flag & D_DIR) dec_ddir(entry, inode); - if(!(flags & D_NO_CLEAR_INODE) && + if (!(flags & D_NO_CLEAR_INODE) && !(atomic_read(&inode->i_count) + inode->i_ddir_count + inode->i_dent_count)) { @@ -635,127 +419,87 @@ _clear_inode(inode, 0, 0); } } - if(!(flags & D_NO_FREE) && !(entry->d_flag & D_ZOMBIE)) { - base->free++; - if(base->free == base->maxfree) { -#ifndef DEBUG - remove_header(free, base); - free_page((unsigned long)base); - goto done; -#endif - } - entry->d_next = base->emptylist; - base->emptylist = entry; - if(!entry->d_next) { - remove_header(full, base); - insert_header(free, base); - } + if (!(flags & D_NO_FREE) && !(entry->d_flag & D_ZOMBIE)) { + kfree(entry->d_name.name); + kfree(entry); #ifdef DEBUG x_freed++; #endif } -#ifndef DEBUG -done: -#else +#ifdef DEBUG x_free++; #endif } blocking void d_del(struct dentry * entry, int flags) { - int i; - - if(!entry) + if (!entry) return; LOG("d_clear", entry); - if(entry->d_len >= D_MEDIUM) { - if(entry->d_len >= D_LARGE) { - i = 3; - } else { - i = 2; - } - } else if(entry->d_len >= D_SMALL) { - i = 1; - } else { - i = 0; - } - _d_del(entry, &anchors[i], flags); + _d_del(entry, flags); } -static inline struct dentry * __dlookup(struct dentry ** base, - struct qstr * name, - struct qstr * appendix) +static inline struct dentry * __dlookup(struct dentry * base, struct dentry * parent, struct qstr * name) { - struct dentry * tmp = *base; - - if(tmp && name->len) { - int totallen = name->len; + if (base) { + struct dentry * tmp = base; + int len = name->len; + int hash = name->hash; + const unsigned char *str = name->name; - if(appendix) - totallen += appendix->len; do { - if(tmp->d_len == totallen && - !(tmp->d_flag & D_DUPLICATE) && - !strncmp(tmp->d_name, name->name, name->len) && - (!appendix || !strncmp(tmp->d_name+name->len, - appendix->name, appendix->len))) + if (tmp->d_name.hash == hash && + tmp->d_name.len == len && + tmp->d_parent == parent && + !(tmp->d_flag & D_DUPLICATE) && + !memcmp(tmp->d_name.name, str, len)) return tmp; tmp = tmp->d_hash_next; - } while(tmp != *base); + } while(tmp != base); } return NULL; } -struct dentry * d_lookup(struct inode * dir, - struct qstr * name, - struct qstr * appendix) -{ - if(dir->i_dentry) { - struct ddir * ddir = d_dir(dir->i_dentry); - struct dentry ** base = d_base_qstr(ddir, name, appendix); +struct dentry * d_lookup(struct dentry * dir, struct qstr * name) +{ + struct dentry ** base = d_base_qstr(dir, name); - return __dlookup(base, name, appendix); - } - return NULL; + return __dlookup(*base, dir, name); } static /*inline*/ blocking void _d_insert_to_parent(struct dentry * entry, - struct ddir * pdir, + struct dentry * parent, struct inode * inode, - struct qstr * ininame, int flags) { struct dentry ** base; - struct dentry * parent = entry->d_parent; #ifdef DEBUG - if(!pdir->dd_alloced) + if (!parent->dd_alloced) printk("dd_alloced is 0!\n"); #endif - base = d_base_qstr(pdir, ininame, NULL); - if(!(flags & (D_NOCHECKDUP|D_DUPLICATE)) && - __dlookup(base, ininame, NULL)) { + base = d_base_qstr(parent, &entry->d_name); + if (!(flags & (D_NOCHECKDUP|D_DUPLICATE)) && + __dlookup(*base, parent, &entry->d_name)) { d_del(entry, D_NO_CLEAR_INODE); return; } - if(entry->d_flag & D_HASHED) { + if (entry->d_flag & D_HASHED) { printk("VFS: dcache entry is already hashed\n"); return; } - if(!(flags & D_PRELIMINARY)) - pdir->dd_true_hashed++; - pdir->dd_hashed++; + parent->dd_hashed++; insert_hash(base, entry); entry->d_flag |= D_HASHED; - pdir->dd_alloced--; - if(flags & D_BASKET) - insert_basket(&pdir->dd_basketlist, entry); + parent->dd_alloced--; + if (flags & D_BASKET) + insert_basket(&parent->dd_basketlist, entry); #ifdef DEBUG - if(inode && inode->i_dentry && (entry->d_flag & D_DIR)) { + if (inode && inode->i_dentry && (entry->d_flag & D_DIR)) { struct dentry * tmp = inode->i_dentry; printk("Auweia inode=%p entry=%p (%p %p %s)\n", - inode, entry, parent->u.d_inode, parent, parent->d_name); + inode, entry, parent->u.d_inode, parent, parent->d_name.name); printk("entry path="); printpath(entry); printk("\n"); do { TST("auweia",tmp); @@ -765,191 +509,169 @@ printk("\n"); } #endif - if(has_true_sons(pdir)) + if (has_true_sons(parent)) inc_ddir(parent, parent->u.d_inode); - if(!inode && !(flags & D_PRELIMINARY)) { - insert_alias(&pdir->dd_neglist, entry); - pdir->dd_negs++; +} + +/* + * Fill in inode information in the entry. + * + * This turns negative dentries into productive full members + * of society. + */ +void d_instantiate(struct dentry *entry, struct inode * inode, int flags) +{ + entry->d_flag = (entry->d_flag & ~D_NEGATIVE) | flags; - /* Don't allow the negative list to grow too much ... */ - while(pdir->dd_negs > (pdir->dd_true_hashed >> 1) + 5) - d_del(pdir->dd_neglist->d_prev, D_REMOVE); + if (inode && !(flags & D_NEGATIVE)) { + if (entry->d_flag & D_DIR) { + if (inode->i_dentry) { + printk("VFS: creating dcache directory alias\n"); + return; + } + } + insert_alias(&inode->i_dentry, entry); + inode->i_dent_count++; } -} -blocking void d_add(struct dentry * entry, struct inode * inode, - struct qstr * ininame, int flags) + entry->u.d_inode = inode; +} + +blocking void d_add(struct dentry * entry, struct inode * inode, int flags) { struct dentry * parent = entry->d_parent; - struct qstr dummy; - struct ddir * pdir; #ifdef DEBUG - if(inode) + if (inode) xcheck("d_add", inode); - if(IS_ROOT(entry)) { + if (IS_ROOT(entry)) { printk("VFS: d_add for root dentry "); printpath(entry); printk(" -> "); - if(ininame) - printk("%s", ininame->name); printk("\n"); return; } - if(!parent) + if (!parent) panic("d_add with parent==NULL"); LOG("d_add", entry); #endif - if(ininame) { - if(ininame->len != entry->d_len) { - printk("VFS: d_add with wrong string length"); - entry->d_len = ininame->len; /* kludge */ - } - memcpy(entry->d_name, ininame->name, ininame->len); - entry->d_name[ininame->len] = '\0'; - } else { - dummy.name = entry->d_name; - dummy.len = entry->d_len; - ininame = &dummy; - } if(entry->d_flag & D_HASHED) printk("VFS: d_add of already added dcache entry\n"); - pdir = d_dir(parent); - _d_insert_to_parent(entry, pdir, inode, ininame, flags); - entry->d_flag |= flags; - if(inode && !(flags & D_PRELIMINARY)) { - if(entry->d_flag & D_DIR) { - if(inode->i_dentry) { - printk("VFS: creating dcache directory alias\n"); - return; - } - } - insert_alias(&inode->i_dentry, entry); - inode->i_dent_count++; - } - entry->u.d_inode = inode; + _d_insert_to_parent(entry, parent, inode, flags); + d_instantiate(entry, inode, flags); } blocking struct dentry * d_entry(struct dentry * parent, struct qstr * name, struct inode * inode) { - struct ddir * pdir = d_dir(parent); - struct dentry ** base = d_base_qstr(pdir, name, NULL); - struct dentry * found = __dlookup(base, name, NULL); + struct dentry ** base = d_base_qstr(parent, name); + struct dentry * found = __dlookup(*base, parent, name); - if(!found) { + if (!found) { int isdir = (inode && S_ISDIR(inode->i_mode)); - found = d_alloc(parent, name->len, isdir); - if(found) { - d_add(found, inode, name, - isdir ? (D_DIR|D_NOCHECKDUP) : D_NOCHECKDUP); + found = d_alloc(parent, name, isdir); + if (found) { + d_add(found, inode, isdir ? (D_DIR|D_NOCHECKDUP) : D_NOCHECKDUP); } else printk("VFS: problem with d_alloc\n"); } return found; } -blocking void d_entry_preliminary(struct dentry * parent, - struct qstr * name, - unsigned long ino) -{ - struct ddir * pdir = d_dir(parent); - struct dentry ** base = d_base_qstr(pdir, name, NULL); - struct dentry * found = __dlookup(base, name, NULL); - - if(!found && ino) { - struct dentry * new = d_alloc(parent, name->len, 0); - - if(new) { - d_add(new, NULL, name, D_PRELIMINARY|D_NOCHECKDUP); - new->u.d_ino = ino; - } else - printk("VFS: problem with d_alloc\n"); - } +static inline void alloc_new_name(struct dentry * entry, struct qstr *newname) +{ + int alloc_len = NAME_ALLOC_LEN(newname->len); + char *name; + + if (alloc_len == NAME_ALLOC_LEN(entry->d_name.len)) + return; + name = kmalloc(alloc_len, GFP_KERNEL); + if (!name) + printk("out of memory for dcache\n"); + kfree(entry->d_name.name); + memcpy(name, newname->name, newname->len); + name[newname->len] = 0; + entry->d_name.name = name; + entry->d_name.len = newname->len; + entry->d_name.hash = newname->hash; +} + +static inline void d_remove_old_parent(struct dentry * entry) +{ + struct dentry * parent; + struct inode * inode; + + parent = entry->d_parent; + inode = entry->u.d_inode; + _d_remove_from_parent(entry, parent, inode, D_NO_CLEAR_INODE); +} + +static inline void d_add_new_parent(struct dentry * entry, struct inode * new_parent) +{ + struct dentry * parent; + struct inode * inode; + + parent = entry->d_parent = new_parent->i_dentry; + inode = entry->u.d_inode; + + _d_insert_to_parent(entry, parent, inode, entry->d_flag); } -blocking void d_move(struct dentry * entry, struct inode * newdir, - struct qstr * newname, struct qstr * newapp) + +blocking void d_move(struct dentry * entry, struct inode * newdir, struct qstr * newname) { - struct ddir tmp; - struct dentry * new; struct inode * inode; int len; int flags; - if(!entry) + if (!entry) return; inode = entry->u.d_inode; flags = entry->d_flag; - if((flags & D_PRELIMINARY) || !inode) { - if(!(flags & D_PRELIMINARY)) - printk("VFS: trying to move negative dcache entry\n"); + if (!inode) { + printk("VFS: trying to move negative dcache entry\n"); d_del(entry, D_NO_CLEAR_INODE); return; } -#if 0 -printk("d_move %p '%s' -> '%s%s' dent_count=%d\n", inode, entry->d_name, - newname->name, newapp ? newapp->name : "", inode->i_dent_count); -#endif - if(flags & D_ZOMBIE) { + + if (flags & D_ZOMBIE) { printk("VFS: moving zombie entry\n"); } - if(flags & D_DIR) { - struct ddir * ddir = d_dir(entry); - memcpy(&tmp, ddir, sizeof(struct ddir)); + d_remove_old_parent(entry); - /* Simulate empty dir for d_del(). */ - memset(ddir, 0, sizeof(struct ddir)); - } len = newname->len; - if(newapp) { - len += newapp->len; - flags |= D_BASKET; - } else - flags &= ~D_BASKET; - new = d_alloc(newdir->i_dentry, len, flags & D_DIR); - memcpy(new->d_name, newname->name, newname->len); - if(newapp) - memcpy(new->d_name+newname->len, newapp->name, newapp->len); - new->d_name[len] = '\0'; - d_del(entry, D_NO_CLEAR_INODE); - d_add(new, inode, NULL, flags & (D_DIR|D_BASKET)); - if(flags & D_DIR) { - struct ddir * ddir = d_dir(new); + flags &= ~D_BASKET; + alloc_new_name(entry, newname); - memcpy(ddir, &tmp, sizeof(struct ddir)); - } + d_add_new_parent(entry, newdir); } -int d_path(struct dentry * entry, struct inode * chroot, char * buf) +int d_path(struct dentry * entry, struct dentry * chroot, char * buf) { - if(IS_ROOT(entry) || (chroot && entry->u.d_inode == chroot && - !(entry->d_flag & D_PRELIMINARY))) { + if (IS_ROOT(entry) || (chroot && entry == chroot)) { *buf = '/'; return 1; } else { int len = d_path(entry->d_parent, chroot, buf); buf += len; - if(len > 1) { + if (len > 1) { *buf++ = '/'; len++; } - memcpy(buf, entry->d_name, entry->d_len); - return len + entry->d_len; + memcpy(buf, entry->d_name.name, entry->d_name.len); + return len + entry->d_name.len; } } struct dentry * d_basket(struct dentry * dir_entry) { - if(dir_entry && (dir_entry->d_flag & D_DIR)) { - struct ddir * ddir = d_dir(dir_entry); - - return ddir->dd_basketlist; + if (dir_entry && (dir_entry->d_flag & D_DIR)) { + return dir_entry->dd_basketlist; } else return NULL; } @@ -964,72 +686,8 @@ struct dentry * entry = *changing_entry; struct inode * inode; -#ifdef CONFIG_DCACHE_PRELOAD - if(entry->d_flag & D_PRELIMINARY) { - struct qstr name = { entry->d_name, entry->d_len }; - struct ddir * pdir = d_dir(entry->d_parent); - struct dentry ** base = d_base_qstr(pdir, &name, NULL); - struct dentry * found; - unsigned long ino; - struct inode * dir = entry->d_parent->u.d_inode; - TST("d_inode",entry); - ino = entry->u.d_ino; - if(!dir) - d_panic(); - - /* Prevent concurrent d_lookup()s or d_inode()s before - * giving up vfs_lock. This just removes from the parent, - * but does not deallocate it. - */ - - /* !!!!!!! Aiee, here is an unresolved race if somebody - * unlink()s the inode during the iget(). The problem is - * that we need to synchronize externally. Proposed solution: - * put a rw_lock (read-mode) on the parent dir for each - * iget(), lookup() and so on, and a write-mode lock for - * everything that changes the dir (e.g. unlink()), and do - * this consistently everywhere in the generic VFS (not in - * the concrete filesystems). This should kill similar - * races everywhere, with a single clean concept. - * Later, the synchronization stuff can be cleaned out - * of the concrete fs'es. - */ - d_del(entry, D_NO_CLEAR_INODE|D_NO_FREE); - vfs_unlock(); - - /* This circumvents the normal lookup() of pathnames. - * Therefore, preliminary entries must not be used - * (see FS_NO_DCACHE and FS_NO_PRELIM) if the fs does not - * permit fetching *valid* inodes with plain iget(). - */ - inode = __iget(dir->i_sb, ino, 0); - vfs_lock(); - if(!inode) { - printk("VFS: preliminary dcache entry was invalid\n"); - *changing_entry = NULL; - return NULL; - } - xcheck("d_inode iget()", inode); - if((found = __dlookup(base, &name, NULL))) { - d_del(entry, D_NO_CLEAR_INODE); - *changing_entry = found; - } else if(S_ISDIR(inode->i_mode)) { - struct dentry * new = d_alloc(entry->d_parent, entry->d_len, 1); - if(new) - d_add(new, inode, &name, D_DIR); - *changing_entry = new; - - /* Finally deallocate old entry. */ - d_del(entry, D_NO_CLEAR_INODE); - } else { - /* Re-insert to the parent, but now as normal dentry. */ - d_add(entry, inode, NULL, 0); - } - return inode; - } -#endif inode = entry->u.d_inode; - if(inode) { + if (inode) { #ifdef DEBUG xcheck("d_inode", inode); #endif diff -u --recursive --new-file v2.1.43/linux/fs/dquot.c linux/fs/dquot.c --- v2.1.43/linux/fs/dquot.c Mon Jun 16 16:35:57 1997 +++ linux/fs/dquot.c Tue Jul 1 13:47:22 1997 @@ -1038,7 +1038,7 @@ if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS)) dev = 0; else { - int error = namei(NAM_FOLLOW_LINK, special, &ino); + int error = namei(special, &ino); if(error) goto out; dev = ino->i_rdev; diff -u --recursive --new-file v2.1.43/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v2.1.43/linux/fs/ext2/dir.c Mon Jun 16 16:35:57 1997 +++ linux/fs/ext2/dir.c Sat Jul 5 20:53:22 1997 @@ -65,6 +65,7 @@ ext2_mknod, /* mknod */ ext2_rename, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/ext2/file.c linux/fs/ext2/file.c --- v2.1.43/linux/fs/ext2/file.c Mon Jun 16 16:35:57 1997 +++ linux/fs/ext2/file.c Sat Jul 5 20:53:22 1997 @@ -72,6 +72,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ generic_readpage, /* readpage */ NULL, /* writepage */ ext2_bmap, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.43/linux/fs/ext2/namei.c Mon Jun 16 16:35:57 1997 +++ linux/fs/ext2/namei.c Sat Jul 5 23:12:35 1997 @@ -27,6 +27,8 @@ #include #include +extern void d_instantiate(struct dentry *, struct inode *, int); + /* * define how far ahead to read directories while searching them. */ @@ -154,8 +156,7 @@ return NULL; } -int ext2_lookup (struct inode * dir, const char * name, int len, - struct inode ** result) +int ext2_lookup(struct inode * dir,const char * name, int len, struct inode ** result) { unsigned long ino; struct ext2_dir_entry * de; @@ -164,26 +165,22 @@ *result = NULL; if (!dir) return -ENOENT; - if (!S_ISDIR(dir->i_mode)) { - iput (dir); + + if (!S_ISDIR(dir->i_mode)) return -ENOTDIR; - } - if (len > EXT2_NAME_LEN) { - iput (dir); + + if (len > EXT2_NAME_LEN) return -ENAMETOOLONG; - } + ino = dir->i_version; - if (!(bh = ext2_find_entry (dir, name, len, &de))) { - iput (dir); + if (!(bh = ext2_find_entry (dir, name, len, &de))) return -ENOENT; - } + ino = le32_to_cpu(de->inode); brelse (bh); - if (!(*result = iget (dir->i_sb, ino))) { - iput (dir); + if (!(*result = iget (dir->i_sb, ino))) return -EACCES; - } - iput (dir); + return 0; } @@ -347,31 +344,35 @@ return -ENOENT; } -int ext2_create (struct inode * dir,const char * name, int len, int mode, - struct inode ** result) +/* + * By the time this is called, we already have created + * the directory cache entry for the new file, but it + * is so far marked "D_NEGATIVE". + * + * If the create succeeds, remove the D_NEGATIVE flag, + * and fill in the inode information with d_instantiate(). + */ +int ext2_create (struct inode * dir, struct dentry * dentry, int mode) { struct inode * inode; struct buffer_head * bh; struct ext2_dir_entry * de; int err; - *result = NULL; if (!dir) return -ENOENT; inode = ext2_new_inode (dir, mode, &err); - if (!inode) { - iput (dir); + if (!inode) return err; - } + inode->i_op = &ext2_file_inode_operations; inode->i_mode = mode; inode->i_dirt = 1; - bh = ext2_add_entry (dir, name, len, &de, &err); + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); if (!bh) { inode->i_nlink--; inode->i_dirt = 1; iput (inode); - iput (dir); return err; } de->inode = cpu_to_le32(inode->i_ino); @@ -382,13 +383,11 @@ wait_on_buffer (bh); } brelse (bh); - iput (dir); - *result = inode; + d_instantiate(dentry, inode, 0); return 0; } -int ext2_mknod (struct inode * dir, const char * name, int len, int mode, - int rdev) +int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) { struct inode * inode; struct buffer_head * bh; @@ -398,21 +397,13 @@ if (!dir) return -ENOENT; - if (len > EXT2_NAME_LEN) { - iput (dir); + if (dentry->d_name.len > EXT2_NAME_LEN) return -ENAMETOOLONG; - } - bh = ext2_find_entry (dir, name, len, &de); - if (bh) { - brelse (bh); - iput (dir); - return -EEXIST; - } + inode = ext2_new_inode (dir, mode, &err); - if (!inode) { - iput (dir); + if (!inode) return err; - } + inode->i_uid = current->fsuid; inode->i_mode = mode; inode->i_op = NULL; @@ -434,12 +425,11 @@ if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); inode->i_dirt = 1; - bh = ext2_add_entry (dir, name, len, &de, &err); + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); if (!bh) { inode->i_nlink--; inode->i_dirt = 1; - iput (inode); - iput (dir); + iput(inode); return err; } de->inode = cpu_to_le32(inode->i_ino); @@ -449,40 +439,28 @@ ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } - brelse (bh); - iput (dir); - iput (inode); + brelse(bh); + d_instantiate(dentry, inode, 0); return 0; } -int ext2_mkdir (struct inode * dir, const char * name, int len, int mode) +int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) { struct inode * inode; struct buffer_head * bh, * dir_block; struct ext2_dir_entry * de; int err; - if (!dir) - return -ENOENT; - if (len > EXT2_NAME_LEN) { - iput (dir); + if (dentry->d_name.len > EXT2_NAME_LEN) return -ENAMETOOLONG; - } - bh = ext2_find_entry (dir, name, len, &de); - if (bh) { - brelse (bh); - iput (dir); - return -EEXIST; - } - if (dir->i_nlink >= EXT2_LINK_MAX) { - iput (dir); + + if (dir->i_nlink >= EXT2_LINK_MAX) return -EMLINK; - } + inode = ext2_new_inode (dir, S_IFDIR, &err); - if (!inode) { - iput (dir); + if (!inode) return err; - } + inode->i_op = &ext2_dir_inode_operations; inode->i_size = inode->i_sb->s_blocksize; dir_block = ext2_bread (inode, 0, 1, &err); @@ -511,9 +489,8 @@ if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; inode->i_dirt = 1; - bh = ext2_add_entry (dir, name, len, &de, &err); + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); if (!bh) { - iput (dir); inode->i_nlink = 0; inode->i_dirt = 1; iput (inode); @@ -528,8 +505,7 @@ } dir->i_nlink++; dir->i_dirt = 1; - iput (dir); - iput (inode); + d_instantiate(dentry, inode, D_DIR); brelse (bh); return 0; } @@ -593,7 +569,7 @@ return 1; } -int ext2_rmdir (struct inode * dir, const char * name, int len) +int ext2_rmdir (struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; @@ -604,11 +580,10 @@ if (!dir) return -ENOENT; inode = NULL; - if (len > EXT2_NAME_LEN) { - iput (dir); + if (dentry->d_name.len > EXT2_NAME_LEN) return -ENAMETOOLONG; - } - bh = ext2_find_entry (dir, name, len, &de); + + bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); retval = -ENOENT; if (!bh) goto end_rmdir; @@ -676,13 +651,12 @@ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt = 1; end_rmdir: - iput (dir); iput (inode); brelse (bh); return retval; } -int ext2_unlink (struct inode * dir, const char * name, int len) +int ext2_unlink(struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; @@ -690,15 +664,12 @@ struct ext2_dir_entry * de; repeat: - if (!dir) - return -ENOENT; retval = -ENOENT; inode = NULL; - if (len > EXT2_NAME_LEN) { - iput (dir); + if (dentry->d_name.len > EXT2_NAME_LEN) return -ENAMETOOLONG; - } - bh = ext2_find_entry (dir, name, len, &de); + + bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); if (!bh) goto end_unlink; if (!(inode = iget (dir->i_sb, le32_to_cpu(de->inode)))) @@ -745,12 +716,10 @@ end_unlink: brelse (bh); iput (inode); - iput (dir); return retval; } -int ext2_symlink (struct inode * dir, const char * name, int len, - const char * symname) +int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname) { struct ext2_dir_entry * de; struct inode * inode = NULL; @@ -761,7 +730,6 @@ char c; if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) { - iput (dir); return err; } inode->i_mode = S_IFLNK | S_IRWXUGO; @@ -775,7 +743,6 @@ name_block = ext2_bread (inode, 0, 1, &err); if (!name_block) { - iput (dir); inode->i_nlink--; inode->i_dirt = 1; iput (inode); @@ -799,21 +766,19 @@ inode->i_size = i; inode->i_dirt = 1; - bh = ext2_find_entry (dir, name, len, &de); + bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { inode->i_nlink--; inode->i_dirt = 1; iput (inode); brelse (bh); - iput (dir); return -EEXIST; } - bh = ext2_add_entry (dir, name, len, &de, &err); + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); if (!bh) { inode->i_nlink--; inode->i_dirt = 1; iput (inode); - iput (dir); return err; } de->inode = cpu_to_le32(inode->i_ino); @@ -824,46 +789,36 @@ wait_on_buffer (bh); } brelse (bh); - iput (dir); + d_instantiate(dentry, inode, 0); iput (inode); return 0; } -int ext2_link (struct inode * oldinode, struct inode * dir, - const char * name, int len) +int ext2_link (struct inode * oldinode, struct inode * dir, struct dentry *dentry) { struct ext2_dir_entry * de; struct buffer_head * bh; int err; - if (S_ISDIR(oldinode->i_mode)) { - iput (oldinode); - iput (dir); + if (S_ISDIR(oldinode->i_mode)) return -EPERM; - } - if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) { - iput (oldinode); - iput (dir); + + if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) return -EPERM; - } - if (oldinode->i_nlink >= EXT2_LINK_MAX) { - iput (oldinode); - iput (dir); + + if (oldinode->i_nlink >= EXT2_LINK_MAX) return -EMLINK; - } - bh = ext2_find_entry (dir, name, len, &de); + + bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { brelse (bh); - iput (dir); - iput (oldinode); return -EEXIST; } - bh = ext2_add_entry (dir, name, len, &de, &err); - if (!bh) { - iput (dir); - iput (oldinode); + + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!bh) return err; - } + de->inode = cpu_to_le32(oldinode->i_ino); dir->i_version = ++event; mark_buffer_dirty(bh, 1); @@ -872,11 +827,10 @@ wait_on_buffer (bh); } brelse (bh); - iput (dir); oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; oldinode->i_dirt = 1; - iput (oldinode); + d_instantiate(dentry, oldinode, 0); return 0; } @@ -923,9 +877,8 @@ * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ -static int do_ext2_rename (struct inode * old_dir, const char * old_name, - int old_len, struct inode * new_dir, - const char * new_name, int new_len) +static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry, + struct inode * new_dir,struct dentry *new_dentry) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; @@ -950,14 +903,14 @@ old_bh = new_bh = dir_bh = NULL; new_de = NULL; retval = -ENAMETOOLONG; - if (old_len > EXT2_NAME_LEN) + if (old_dentry->d_name.len > EXT2_NAME_LEN) goto end_rename; - old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de); + old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; if (!old_bh) goto end_rename; - old_inode = __iget (old_dir->i_sb, le32_to_cpu(old_de->inode), 0); /* don't cross mnt-points */ + old_inode = iget (old_dir->i_sb, le32_to_cpu(old_de->inode)); if (!old_inode) goto end_rename; retval = -EPERM; @@ -967,9 +920,9 @@ goto end_rename; if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode)) goto end_rename; - new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de); + new_bh = ext2_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { - new_inode = __iget (new_dir->i_sb, le32_to_cpu(new_de->inode), 0); /* no mntp cross */ + new_inode = iget (new_dir->i_sb, le32_to_cpu(new_de->inode)); if (!new_inode) { brelse (new_bh); new_bh = NULL; @@ -1018,7 +971,7 @@ goto end_rename; } if (!new_bh) - new_bh = ext2_add_entry (new_dir, new_name, new_len, &new_de, + new_bh = ext2_add_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de, &retval); if (!new_bh) goto end_rename; @@ -1079,8 +1032,6 @@ brelse (new_bh); iput (old_inode); iput (new_inode); - iput (old_dir); - iput (new_dir); return retval; } @@ -1097,16 +1048,15 @@ * super-block. This way, we really lock other renames only if they occur * on the same file system */ -int ext2_rename (struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len) +int ext2_rename (struct inode * old_dir, struct dentry *old_dentry, + struct inode * new_dir, struct dentry *new_dentry) { int result; while (old_dir->i_sb->u.ext2_sb.s_rename_lock) sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait); old_dir->i_sb->u.ext2_sb.s_rename_lock = 1; - result = do_ext2_rename (old_dir, old_name, old_len, new_dir, - new_name, new_len); + result = do_ext2_rename (old_dir, old_dentry, new_dir, new_dentry); old_dir->i_sb->u.ext2_sb.s_rename_lock = 0; wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait); return result; diff -u --recursive --new-file v2.1.43/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v2.1.43/linux/fs/ext2/super.c Mon Jun 16 16:35:57 1997 +++ linux/fs/ext2/super.c Tue Jul 1 16:42:12 1997 @@ -632,7 +632,8 @@ */ sb->s_dev = dev; sb->s_op = &ext2_sops; - if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) { + sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO), NULL); + if (!sb->s_root) { sb->s_dev = 0; for (i = 0; i < db_count; i++) if (sb->u.ext2_sb.s_group_desc[i]) diff -u --recursive --new-file v2.1.43/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c --- v2.1.43/linux/fs/ext2/symlink.c Mon Jun 16 16:35:57 1997 +++ linux/fs/ext2/symlink.c Sat Jul 5 20:53:22 1997 @@ -25,6 +25,7 @@ #include static int ext2_readlink (struct inode *, char *, int); +static struct dentry *ext2_follow_link(struct inode *, struct dentry *); /* * symlinks can't do much... @@ -41,6 +42,7 @@ NULL, /* mknod */ NULL, /* rename */ ext2_readlink, /* readlink */ + ext2_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -49,6 +51,30 @@ NULL /* smap */ }; +static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *base) +{ + int error; + struct buffer_head * bh = NULL; + char * link; + + link = (char *) inode->u.ext2_i.i_data; + if (inode->i_blocks) { + if (!(bh = ext2_bread (inode, 0, 0, &error))) { + dput(base); + return ERR_PTR(-EIO); + } + link = bh->b_data; + } + if (!IS_RDONLY(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } + base = lookup_dentry(link, base, 1); + if (bh) + brelse(bh); + return base; +} + static int ext2_readlink (struct inode * inode, char * buffer, int buflen) { struct buffer_head * bh = NULL; @@ -60,7 +86,6 @@ if (inode->i_blocks) { bh = ext2_bread (inode, 0, 0, &err); if (!bh) { - iput (inode); if(err < 0) /* indicate type of error */ return err; return 0; @@ -79,7 +104,6 @@ inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } - iput (inode); if (bh) brelse (bh); return i; diff -u --recursive --new-file v2.1.43/linux/fs/fat/misc.c linux/fs/fat/misc.c --- v2.1.43/linux/fs/fat/misc.c Mon Apr 14 16:28:17 1997 +++ linux/fs/fat/misc.c Thu Jul 3 13:18:33 1997 @@ -19,13 +19,14 @@ /* Well-known binary file extensions - of course there are many more */ -static char bin_extensions[] = - "EXE" "COM" "BIN" "APP" "SYS" "DRV" "OVL" "OVR" "OBJ" "LIB" "DLL" "PIF" /* program code */ - "ARC" "ZIP" "LHA" "LZH" "ZOO" "TAR" "Z " "ARJ" /* common archivers */ - "TZ " "TAZ" "TZP" "TPZ" /* abbreviations of tar.Z and tar.zip */ - "GZ " "TGZ" "DEB" /* .gz, .tar.gz and Debian packages */ - "GIF" "BMP" "TIF" "GL " "JPG" "PCX" /* graphics */ - "TFM" "VF " "GF " "PK " "PXL" "DVI"; /* TeX */ +static char ascii_extensions[] = + "TXT" "ME " "HTM" "1ST" "LOG" " " /* text files */ + "C " "H " "CPP" "LIS" "PAS" "FOR" /* programming languages */ + "F " "MAK" "INC" "BAS" /* programming languages */ + "BAT" "SH " /* program code :) */ + "INI" /* config files */ + "PBM" "PGM" "DXF" /* graphics */ + "TEX"; /* TeX */ /* @@ -62,9 +63,9 @@ case 't': return 0; case 'a': - for (walk = bin_extensions; *walk; walk += 3) - if (!strncmp(extension,walk,3)) return 1; - return 0; + for (walk = ascii_extensions; *walk; walk += 3) + if (!strncmp(extension,walk,3)) return 0; + return 1; /* default binary conversion */ default: printk("Invalid conversion mode - defaulting to " "binary.\n"); diff -u --recursive --new-file v2.1.43/linux/fs/inode.c linux/fs/inode.c --- v2.1.43/linux/fs/inode.c Mon Jun 16 16:35:57 1997 +++ linux/fs/inode.c Sat Jul 5 20:53:22 1997 @@ -110,7 +110,7 @@ { int i; for(i=xcnt-1; i>=0; i--) - if(xtst[i] == p) + if (xtst[i] == p) return; printk("Bogus inode %p in %s\n", p, txt); } @@ -123,7 +123,7 @@ struct inode * res; struct inode * inode = res = (struct inode*)__get_free_page(GFP_KERNEL); int size = PAGE_SIZE; - if(!inode) + if (!inode) return NULL; size -= sizeof(struct inode); @@ -178,7 +178,7 @@ int res = 0; vfs_lock(); inode->i_status &= ~flags; - if(inode->i_status & ST_WAITING) { + if (inode->i_status & ST_WAITING) { inode->i_status &= ~ST_WAITING; vfs_unlock(); wake_up(&inode->i_wait); @@ -191,10 +191,10 @@ unsigned short waitflags, unsigned short setflags) { /* Do nothing if the same op is already in progress. */ - if(op && !(inode->i_status & setflags)) { + if (op && !(inode->i_status & setflags)) { set_io(inode, waitflags, setflags); op(inode); - if(release_io(inode, setflags)) { + if (release_io(inode, setflags)) { /* Somebody grabbed my inode from under me. */ #ifdef DEBUG printk("_io grab!\n"); @@ -206,7 +206,7 @@ blocking int _free_ibasket(struct super_block * sb) { - if(sb->s_ibasket) { + if (sb->s_ibasket) { struct inode * delinquish = sb->s_ibasket->i_basket_prev; #if 0 printpath(delinquish->i_dentry); @@ -221,11 +221,11 @@ static /*inline*/ void _put_ibasket(struct inode * inode) { struct super_block * sb = inode->i_sb; - if(!(inode->i_status & ST_IBASKET)) { + if (!(inode->i_status & ST_IBASKET)) { inode->i_status |= ST_IBASKET; insert_ibasket(&sb->s_ibasket, inode); sb->s_ibasket_count++; - if(sb->s_ibasket_count > sb->s_ibasket_max) + if (sb->s_ibasket_count > sb->s_ibasket_max) (void)_free_ibasket(sb); } } @@ -233,7 +233,7 @@ blocking void _clear_inode(struct inode * inode, int external, int verbose) { xcheck("_clear_inode",inode); - if(inode->i_status & ST_IBASKET) { + if (inode->i_status & ST_IBASKET) { struct super_block * sb = inode->i_sb; remove_ibasket(&sb->s_ibasket, inode); sb->s_ibasket_count--; @@ -243,32 +243,32 @@ printk(" put_inode\n"); #endif _io(sb->s_op->put_inode, inode, ST_TO_PUT|ST_TO_WRITE, ST_TO_PUT); - if(inode->i_status & ST_EMPTY) + if (inode->i_status & ST_EMPTY) return; } - if(inode->i_status & ST_HASHED) + if (inode->i_status & ST_HASHED) remove_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode); - if(inode->i_status & ST_AGED) { + if (inode->i_status & ST_AGED) { /* "cannot happen" when called from an fs because at least * the caller must use it. Can happen when called from * invalidate_inodes(). */ - if(verbose) + if (verbose) printk("VFS: clearing aged inode\n"); - if(atomic_read(&inode->i_count)) + if (atomic_read(&inode->i_count)) printk("VFS: aged inode is in use\n"); remove_lru(&aged_i[inode->i_level], inode); inodes_stat.aged_count[inode->i_level]--; } - if(!external && inode->i_status & ST_IO) { + if (!external && inode->i_status & ST_IO) { printk("VFS: clearing inode during IO operation\n"); } - if(!(inode->i_status & ST_EMPTY)) { + if (!(inode->i_status & ST_EMPTY)) { remove_all(&all_i, inode); inode->i_status = ST_EMPTY; while(inode->i_dentry) { d_del(inode->i_dentry, D_NO_CLEAR_INODE); } - if(inode->i_pages) { + if (inode->i_pages) { vfs_unlock(); /* may block, can that be revised? */ truncate_inode_pages(inode, 0); vfs_lock(); @@ -291,7 +291,7 @@ { xcheck("insert_inode_hash",inode); vfs_lock(); - if(!(inode->i_status & ST_HASHED)) { + if (!(inode->i_status & ST_HASHED)) { insert_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode); inode->i_status |= ST_HASHED; } else @@ -306,42 +306,42 @@ retry: inode = empty_i; - if(inode) { + if (inode) { remove_all(&empty_i, inode); inodes_stat.nr_free_inodes--; } else if(inodes_stat.nr_inodes < max_inodes || retry > 2) { inode = grow_inodes(); } - if(!inode) { + if (!inode) { int level; int usable = 0; for(level = 0; level <= NR_LEVELS; level++) - if(aged_i[level]) { + if (aged_i[level]) { inode = aged_i[level]->i_lru_prev; /* Here is the picking strategy, tune this */ - if(aged_reused[level] < (usable++ ? + if (aged_reused[level] < (usable++ ? inodes_stat.aged_count[level] : 2)) break; aged_reused[level] = 0; } - if(inode) { - if(!(inode->i_status & ST_AGED)) + if (inode) { + if (!(inode->i_status & ST_AGED)) printk("VFS: inode aging inconsistency\n"); - if(atomic_read(&inode->i_count) + inode->i_ddir_count) + if (atomic_read(&inode->i_count) + inode->i_ddir_count) printk("VFS: i_count of aged inode is not zero\n"); - if(inode->i_dirt) + if (inode->i_dirt) printk("VFS: Hey, somebody made my aged inode dirty\n"); _clear_inode(inode, 0, 0); goto retry; } } - if(!inode) { + if (!inode) { vfs_unlock(); schedule(); - if(retry > 10) + if (retry > 10) panic("VFS: cannot repair inode shortage"); - if(retry > 2) + if (retry > 2) printk("VFS: no free inodes\n"); retry++; vfs_lock(); @@ -363,8 +363,8 @@ { struct inode ** base = &hashtable[hash(i_dev, i_ino)]; struct inode * inode = *base; - if(inode) do { - if(inode->i_ino == i_ino && inode->i_dev == i_dev) { + if (inode) do { + if (inode->i_ino == i_ino && inode->i_dev == i_dev) { atomic_inc(&inode->i_count); printk("VFS: inode %lx is already in use\n", i_ino); return inode; @@ -391,17 +391,17 @@ void _get_inode(struct inode * inode) { - if(inode->i_status & ST_IBASKET) { + if (inode->i_status & ST_IBASKET) { inode->i_status &= ~ST_IBASKET; remove_ibasket(&inode->i_sb->s_ibasket, inode); inode->i_sb->s_ibasket_count--; } - if(inode->i_status & ST_AGED) { + if (inode->i_status & ST_AGED) { inode->i_status &= ~ST_AGED; remove_lru(&aged_i[inode->i_level], inode); inodes_stat.aged_count[inode->i_level]--; aged_reused[inode->i_level]++; - if(S_ISDIR(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) /* make dirs less thrashable */ inode->i_level = NR_LEVELS-1; else if(inode->i_nlink > 1) @@ -410,30 +410,28 @@ else if(++inode->i_reuse_count >= age_table[inode->i_level] && inode->i_level < NR_LEVELS-1) inode->i_level++; - if(atomic_read(&inode->i_count) != 1) - printk("VFS: inode count was not zero\n"); + if (atomic_read(&inode->i_count) != 1) + printk("VFS: inode count was not zero (%d after ++)\n", atomic_read(&inode->i_count)); } else if(inode->i_status & ST_EMPTY) printk("VFS: invalid reuse of empty inode\n"); } -blocking struct inode * __iget(struct super_block * sb, - unsigned long i_ino, - int crossmntp) +blocking struct inode * iget(struct super_block * sb, unsigned long i_ino) { struct inode ** base; struct inode * inode; dev_t i_dev; - if(!sb) + if (!sb) panic("VFS: iget with sb == NULL"); i_dev = sb->s_dev; - if(!i_dev) + if (!i_dev) panic("VFS: sb->s_dev is NULL\n"); base = &hashtable[hash(i_dev, i_ino)]; vfs_lock(); inode = *base; - if(inode) do { - if(inode->i_ino == i_ino && inode->i_dev == i_dev) { + if (inode) do { + if (inode->i_ino == i_ino && inode->i_dev == i_dev) { atomic_inc(&inode->i_count); _get_inode(inode); @@ -455,21 +453,14 @@ inode = _get_empty_inode_hashed(i_dev, i_ino); inode->i_sb = sb; inode->i_flags = sb->s_flags; - if(sb->s_op && sb->s_op->read_inode) { + if (sb->s_op && sb->s_op->read_inode) { set_io(inode, 0, ST_TO_READ); /* do not wait at all */ sb->s_op->read_inode(inode); - if(release_io(inode, ST_TO_READ)) + if (release_io(inode, ST_TO_READ)) goto done; } vfs_unlock(); done: - while(crossmntp && inode->i_mount) { - struct inode * tmp = inode->i_mount; - iinc(tmp); - iput(inode); - inode = tmp; - } -xcheck("_iget",inode); return inode; } @@ -477,68 +468,66 @@ { struct super_block * sb; xcheck("_iput",inode); - if(atomic_read(&inode->i_count) + inode->i_ddir_count < 0) + + if (atomic_read(&inode->i_count) < 0) printk("VFS: i_count is negative\n"); - if((atomic_read(&inode->i_count) + inode->i_ddir_count) || + if (inode->i_ddir_count < 0) + printk("VFS: i_ddir_count is negative\n"); + + if ((atomic_read(&inode->i_count) + inode->i_ddir_count) || (inode->i_status & ST_FREEING)) { return; } inode->i_status |= ST_FREEING; -#ifdef CONFIG_OMIRR - if(inode->i_status & ST_MODIFIED) { - inode->i_status &= ~ST_MODIFIED; - omirr_printall(inode, " W %ld ", CURRENT_TIME); - } -#endif - if(inode->i_pipe) { + if (inode->i_pipe) { free_page((unsigned long)PIPE_BASE(*inode)); PIPE_BASE(*inode)= NULL; } - if((sb = inode->i_sb)) { - if(sb->s_type && (sb->s_type->fs_flags & FS_NO_DCACHE)) { + if ((sb = inode->i_sb)) { + if (sb->s_type && (sb->s_type->fs_flags & FS_NO_DCACHE)) { while(inode->i_dentry) d_del(inode->i_dentry, D_NO_CLEAR_INODE); - if(atomic_read(&inode->i_count) + inode->i_ddir_count) + if (atomic_read(&inode->i_count) + inode->i_ddir_count) goto done; } - if(sb->s_op) { - if(inode->i_nlink <= 0 && inode->i_dent_count && + if (sb->s_op) { + if (inode->i_nlink <= 0 && inode->i_dent_count && !(inode->i_status & (ST_EMPTY|ST_IBASKET)) && (sb->s_type->fs_flags & FS_IBASKET)) { _put_ibasket(inode); goto done; } - if(!inode->i_dent_count || + if (!inode->i_dent_count || (sb->s_type->fs_flags & FS_NO_DCACHE)) { _io(sb->s_op->put_inode, inode, ST_TO_PUT|ST_TO_WRITE, ST_TO_PUT); - if(atomic_read(&inode->i_count) + inode->i_ddir_count) + if (atomic_read(&inode->i_count) + inode->i_ddir_count) goto done; - if(inode->i_nlink <= 0) { - if(!(inode->i_status & ST_EMPTY)) { + if (inode->i_nlink <= 0) { + if (!(inode->i_status & ST_EMPTY)) { _clear_inode(inode, 0, 1); } goto done; } } - if(inode->i_dirt) { + if (inode->i_dirt) { inode->i_dirt = 0; _io(sb->s_op->write_inode, inode, ST_TO_PUT|ST_TO_WRITE, ST_TO_WRITE); - if(atomic_read(&inode->i_count) + inode->i_ddir_count) + if (atomic_read(&inode->i_count) + inode->i_ddir_count) goto done; } } - if(IS_WRITABLE(inode) && sb->dq_op) { + if (IS_WRITABLE(inode) && sb->dq_op) { /* can operate in parallel to other ops ? */ _io(sb->dq_op->drop, inode, 0, ST_TO_DROP); - if(atomic_read(&inode->i_count) + inode->i_ddir_count) + if (atomic_read(&inode->i_count) + inode->i_ddir_count) goto done; } } - if(inode->i_mmap) + if (inode->i_mmap) printk("VFS: inode has mappings\n"); - if(inode->i_status & ST_AGED) { + if (inode->i_status & ST_AGED) { printk("VFS: reaging inode\n"); #if defined(DEBUG) printpath(inode->i_dentry); @@ -546,11 +535,11 @@ #endif goto done; } - if(!(inode->i_status & (ST_HASHED|ST_EMPTY))) { + if (!(inode->i_status & (ST_HASHED|ST_EMPTY))) { _clear_inode(inode, 0, 1); goto done; } - if(inode->i_status & ST_EMPTY) { + if (inode->i_status & ST_EMPTY) { printk("VFS: aging an empty inode\n"); goto done; } @@ -573,10 +562,10 @@ struct inode * inode; vfs_lock(); inode = all_i; - if(inode) do { + if (inode) do { xcheck("sync_inodes",inode); - if(inode->i_dirt && (inode->i_dev == dev || !dev)) { - if(inode->i_sb && inode->i_sb->s_op && + if (inode->i_dirt && (inode->i_dev == dev || !dev)) { + if (inode->i_sb && inode->i_sb->s_op && !(inode->i_status & ST_FREEING)) { inode->i_dirt = 0; _io(inode->i_sb->s_op->write_inode, inode, @@ -596,12 +585,12 @@ vfs_lock(); startover: inode = all_i; - if(inode) do { + if (inode) do { struct inode * next; xcheck("_check_inodes",inode); next = inode->i_next; - if(inode->i_dev == dev) { - if(inode->i_dirt || atomic_read(&inode->i_count)) { + if (inode->i_dev == dev) { + if (inode->i_dirt || atomic_read(&inode->i_count)) { bad++; } else { _clear_inode(inode, 0, 0); @@ -609,14 +598,14 @@ /* _clear_inode() may recursively clear other * inodes, probably also the next one. */ - if(next->i_status & ST_EMPTY) + if (next->i_status & ST_EMPTY) goto startover; } } inode = next; } while(inode != all_i); vfs_unlock(); - if(complain && bad) + if (complain && bad) printk("VFS: %d inode(s) busy on removed device `%s'\n", bad, kdevname(dev)); return (bad == 0); @@ -642,16 +631,14 @@ return 1; /* not checked any more */ } -int fs_may_umount(kdev_t dev, struct inode * mount_root) +int fs_may_umount(kdev_t dev, struct dentry * root) { struct inode * inode; vfs_lock(); inode = all_i; - if(inode) do { -xcheck("fs_may_umount",inode); - if(inode->i_dev == dev && atomic_read(&inode->i_count)) - if(inode != mount_root || atomic_read(&inode->i_count) > - (inode->i_mount == inode ? 2 : 1)) { + if (inode) do { + if (inode->i_dev == dev && atomic_read(&inode->i_count)) + if (inode != root->u.d_inode) { vfs_unlock(); return 0; } @@ -668,7 +655,7 @@ struct inode * inode = get_empty_inode(); PIPE_BASE(*inode) = (char*)__get_free_page(GFP_USER); - if(!(PIPE_BASE(*inode))) { + if (!(PIPE_BASE(*inode))) { iput(inode); return NULL; } @@ -682,21 +669,6 @@ inode->i_op = &pipe_inode_operations; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; - /* I hope this does not introduce security problems. - * Please check and give me response. - */ - { - char dummyname[32]; - struct qstr dummy = { dummyname, 0 }; - struct dentry * new; - sprintf(dummyname, ".anonymous-pipe-%06lud", inode->i_ino); - dummy.len = strlen(dummyname); - vfs_lock(); - new = d_alloc(the_root, dummy.len, 0); - if(new) - d_add(new, inode, &dummy, D_BASKET); - vfs_unlock(); - } return inode; } diff -u --recursive --new-file v2.1.43/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v2.1.43/linux/fs/minix/namei.c Mon Jun 16 16:35:57 1997 +++ linux/fs/minix/namei.c Thu Jul 3 17:30:52 1997 @@ -697,7 +697,7 @@ retval = -ENOENT; if (!old_bh) goto end_rename; - old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */ + old_inode = __iget(old_dir->i_sb, old_de->inode); if (!old_inode) goto end_rename; retval = -EPERM; @@ -707,7 +707,7 @@ goto end_rename; new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de); if (new_bh) { - new_inode = __iget(new_dir->i_sb, new_de->inode, 0); + new_inode = __iget(new_dir->i_sb, new_de->inode); if (!new_inode) { brelse(new_bh); new_bh = NULL; diff -u --recursive --new-file v2.1.43/linux/fs/namei.c linux/fs/namei.c --- v2.1.43/linux/fs/namei.c Mon Jun 16 16:35:58 1997 +++ linux/fs/namei.c Sat Jul 5 23:12:35 1997 @@ -12,7 +12,6 @@ * lookup logic. */ -#include #include #include #include @@ -37,10 +36,6 @@ #undef DEBUG /* some other debugging */ -/* local flags for __namei() */ -#define NAM_SEMLOCK 8 /* set a semlock on the last dir */ -#define NAM_TRANSCREATE 16 /* last component may be created, try "=CREATE#" suffix*/ -#define NAM_NO_TRAILSLASH 32 /* disallow trailing slashes by returning EISDIR */ #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) /* [Feb-1997 T. Schoebel-Theuer] @@ -56,7 +51,7 @@ * is done solely in the VFS level, such that _follow_link() is not * used any more and could be removed in future. As a side effect, * dir_namei(), _namei() and follow_link() are now replaced with a single - * function __namei() that can handle all the special cases of the former + * function lookup_dentry() that can handle all the special cases of the former * code. * * With the new dcache, the pathname is stored at each inode, at least as @@ -95,13 +90,13 @@ char * res; down(&quicklock); res = quicklist; - if(res) { + if (res) { #ifdef DEBUG char * tmp = res; int i; for(i=0; i (unsigned long)(-1000)) + inline void putname(char * name) { - if(name) { + if (name) { down(&quicklock); *(char**)name = quicklist; quicklist = name; @@ -160,7 +167,7 @@ int retval; tmp = get_page(); - if(!tmp) + if (!tmp) return -ENOMEM; retval = do_getname(filename, tmp); if (retval < 0) @@ -222,417 +229,211 @@ inode->i_writecount--; } -static /*inline */ int concat(struct qstr * name, struct qstr * appendix, char * buf) -{ - int totallen = name->len; - if(name->len > MAX_TRANS_FILELEN || - appendix->len > MAX_TRANS_SUFFIX) { - return -ENAMETOOLONG; - } - memcpy(buf, name->name, name->len); - memcpy(buf + name->len, appendix->name, appendix->len); - totallen += appendix->len; - buf[totallen] = '\0'; - return totallen; -} - -/* Internal lookup() using the new generic dcache. - * buf must only be supplied if appendix!=NULL. +/* + * This is called when everything else fails, and we actually have + * to go to the low-level filesystem to find out what we should do.. + * + * We get the directory semaphore, and after getting that we also + * make sure that nobody added the entry to the dcache in the meantime.. */ -static int cached_lookup(struct inode * dir, struct qstr * name, - struct qstr * appendix, char * buf, - struct qstr * res_name, struct dentry ** res_entry, - struct inode ** result) +static struct dentry * real_lookup(struct dentry * dentry, struct qstr * name) { - struct qstr tmp = { name->name, name->len }; - int error; - struct dentry * cached; + struct inode *dir = dentry->u.d_inode; + struct dentry *cached; - *result = NULL; - if(name->len >= D_MAXLEN) - return -ENAMETOOLONG; - vfs_lock(); - cached = d_lookup(dir, name, appendix); - if(cached) { - struct inode *inode = NULL; + down(&dir->i_sem); - if(cached->u.d_inode && (inode = d_inode(&cached))) { - error = 0; - if(appendix && res_name) { - tmp.len = error = concat(name, appendix, buf); - tmp.name = buf; - if(error > 0) - error = 0; - } - } else { - error = -ENOENT; - } - vfs_unlock(); - if(res_entry) - *res_entry = cached; + cached = d_lookup(dentry, name); - /* Since we are bypassing the iget() mechanism, we have to - * fabricate the act of crossing any mount points. - */ - if(!error && inode && inode->i_mount) { - do { - struct inode *mnti = inode->i_mount; - iinc(mnti); - iput(inode); - inode = mnti; - } while(inode->i_mount); + if (!cached) { + struct inode *inode; + int error = -ENOTDIR; + + if (dir->i_op && dir->i_op->lookup) + error = dir->i_op->lookup(dir, name->name, name->len, &inode); + cached = ERR_PTR(error); + if (!error || error == -ENOENT) { + int isdir = 0, flags = D_NOCHECKDUP; + + if (error) { + flags = D_NEGATIVE; + inode = NULL; + } else if (S_ISDIR(inode->i_mode)) { + isdir = 1; + flags = D_DIR|D_NOCHECKDUP; + } + cached = d_alloc(dentry, name, isdir); + d_add(cached, inode, flags); } - *result = inode; - goto done; - } else - vfs_unlock(); - - if(appendix) { - tmp.len = error = concat(name, appendix, buf); - tmp.name = buf; - if(error < 0) - goto done; - } - atomic_inc(&dir->i_count); - error = dir->i_op->lookup(dir, tmp.name, tmp.len, result); - if(dir->i_dentry && tmp.len && - (!error || (error == -ENOENT && (!dir->i_sb || !dir->i_sb->s_type || - !(dir->i_sb->s_type->fs_flags & FS_NO_DCACHE))))) { - struct dentry * res; - vfs_lock(); - res = d_entry(dir->i_dentry, &tmp, error ? NULL : *result); - vfs_unlock(); - if(res_entry) - *res_entry = res; } -done: - if(res_name) { - if(error) { - res_name->name = name->name; - res_name->len = name->len; - } else { - res_name->name = tmp.name; - res_name->len = tmp.len; - } - } - return error; + up(&dir->i_sem); + return cached; +} + +/* Internal lookup() using the new generic dcache. */ +static inline struct dentry * cached_lookup(struct dentry * dentry, struct qstr * name) +{ + return d_lookup(dentry, name); } -#ifdef CONFIG_TRANS_NAMES -/* If a normal filename is seen, try to determine whether a - * "#keyword=context#" file exists and return the new filename. - * If the name is to be created (create_mode), check whether a - * "#keyword=CREATE" name exists and optionally return the corresponding - * context name even if it didn't exist before. +/* + * "." and ".." are special - ".." especially so because it has to be able + * to know about the current root directory and parent relationships */ -static int check_suffixes(struct inode * dir, struct qstr * name, - int create_mode, char * buf, - struct qstr * res_name, struct dentry ** res_entry, - struct inode ** result) -{ - struct translations * trans; - char * env; - struct qstr * suffixes; - int i; - int error = -ENOENT; - - if(!buf) - panic("buf==NULL"); - env = env_transl(); -#ifdef CONFIG_TRANS_RESTRICT - if(!env && dir->i_gid != CONFIG_TRANS_GID) { - return error; - } -#endif - trans = get_translations(env); - suffixes = create_mode ? trans->c_name : trans->name; - for(i = 0; i < trans->count; i++) { - error = cached_lookup(dir, name, &suffixes[i], - buf, res_name, res_entry, result); - if(!error) { - if(res_name && create_mode) { - /* buf == res_name->name, but is writable */ - memcpy(buf + name->len, - trans->name[i].name, - trans->name[i].len); - res_name->len = name->len + trans->name[i].len; - buf[res_name->len] = '\0'; +static struct dentry * reserved_lookup(struct dentry * dir, struct qstr * name) +{ + struct dentry *result = NULL; + if (name->name[0] == '.') { + switch (name->len) { + default: + break; + case 2: + if (name->name[1] != '.') + break; + + if (dir != current->fs->root) { + dir = dir->d_covers->d_parent; } + /* fallthrough */ + case 1: + result = dget(dir); break; } } - if(env) - free_page((unsigned long)trans); - return error; + return result; } -#endif - -/* Any operations involving reserved names at the VFS level should go here. */ -static /*inline*/ int reserved_lookup(struct inode * dir, struct qstr * name, - int create_mode, char * buf, - struct inode ** result) -{ - int error = -ENOENT; - if(name->name[0] == '.') { - if(name->len == 1) { - *result = dir; - error = 0; - } else if (name->len==2 && name->name[1] == '.') { - if (dir == current->fs->root) { - *result = dir; - error = 0; - } - else if(dir->i_dentry) { - error = 0; - *result = dir->i_dentry->d_parent->u.d_inode; - if(!*result) { - printk("dcache parent directory is lost"); - error = -ESTALE; /* random error */ - } - } +static inline int is_reserved(struct dentry *dentry) +{ + if (dentry->d_name.name[0] == '.') { + switch (dentry->d_name.len) { + case 2: + if (dentry->d_name.name[1] != '.') + break; + /* fallthrough */ + case 1: + return 1; } - if(!error) - atomic_inc(&(*result)->i_count); } - return error; + return 0; } /* In difference to the former version, lookup() no longer eats the dir. */ -static /*inline*/ int lookup(struct inode * dir, struct qstr * name, int create_mode, - char * buf, struct qstr * res_name, - struct dentry ** res_entry, struct inode ** result) -{ - int perm; - - *result = NULL; - perm = -ENOENT; - if (!dir) +static struct dentry * lookup(struct dentry * dir, struct qstr * name) +{ + int err; + struct dentry * result; + + result = ERR_PTR(-ENOTDIR); + if (!(dir->d_flag & D_DIR)) goto done; /* Check permissions before traversing mount-points. */ - perm = permission(dir,MAY_EXEC); - if (perm) + err = permission(dir->u.d_inode, MAY_EXEC); + result = ERR_PTR(err); + if (err) goto done; - perm = reserved_lookup(dir, name, create_mode, buf, result); - if(!perm) { - if(res_name) { - res_name->name = name->name; - res_name->len = name->len; - } + + result = reserved_lookup(dir, name); + if (result) goto done; - } - perm = -ENOTDIR; - if (!dir->i_op || !dir->i_op->lookup) + + result = cached_lookup(dir, name); + if (result) goto done; -#ifdef CONFIG_TRANS_NAMES /* try suffixes */ - perm = check_suffixes(dir, name, 0, buf, res_name, res_entry, result); - if(perm) /* try original name */ -#endif - perm = cached_lookup(dir, name, NULL, buf, res_name, res_entry, result); -#ifdef CONFIG_TRANS_NAMES - if(perm == -ENOENT && create_mode) { /* try the =CREATE# suffix */ - struct inode * dummy; - if(!check_suffixes(dir, name, 1, buf, res_name, NULL, &dummy)) { - iput(dummy); - } - } -#endif + + result = real_lookup(dir, name); + if (!result) + result = ERR_PTR(-ENOTDIR); done: - return perm; + if (!IS_ERR(result)) + result = dget(result->d_mounts); + + return result; } -/* [8-Feb-97 T. Schoebel-Theuer] follow_link() modified for generic operation - * on the VFS layer: first call _readlink() and then open_namei(). - * All _follow_link() are not used any more and may be eliminated - * (by Linus; I refrained in order to not break other patches). - * Single exeption is procfs, where proc_follow_link() is used - * internally (and perhaps should be rewritten). - * Note: [partly obsolete] I removed parameters flag and mode, since now - * __namei() is called instead of open_namei(). In the old semantics, - * the _last_ instance of open_namei() did the real create() if O_CREAT was - * set and the name existed already in form of a symlink. This has been - * simplified now, and also the semantics when combined with O_EXCL has changed. - **************************************************************************** - * [13-Feb-97] Complete rewrite -> functionality of reading symlinks factored - * out into _read_link(). The above notes remain valid in principle. +/* + * This should check "link_count", but doesn't do that yet.. */ -static /*inline*/ int _read_link(struct inode * inode, char ** linkname, int loopcount) +static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry) { - unsigned long old_fs; - int error; + struct inode * inode = dentry->u.d_inode; - error = -ENOSYS; - if (!inode->i_op || !inode->i_op->readlink) - goto done; - error = -ELOOP; - if (current->link_count + loopcount > 10) - goto done; - error = -ENOMEM; - if(!*linkname && !(*linkname = get_page())) - goto done; - if (DO_UPDATE_ATIME(inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - atomic_inc(&inode->i_count); - old_fs = get_fs(); - set_fs(KERNEL_DS); - error = inode->i_op->readlink(inode, *linkname, PAGE_SIZE); - set_fs(old_fs); - if(!error) { - error = -ENOENT; /* ? or other error code ? */ - } else if(error > 0) { - (*linkname)[error] = '\0'; - error = 0; + if (inode->i_op && inode->i_op->follow_link) { + struct dentry *result; + + /* This eats the base */ + result = inode->i_op->follow_link(inode, base); + base = dentry; + dentry = result; } -done: - iput(inode); - return error; + dput(base); + return dentry; } -/* [13-Feb-97 T. Schoebel-Theuer] complete rewrite: - * merged dir_name(), _namei() and follow_link() into one new routine - * that obeys all the special cases hidden in the old routines in a - * (hopefully) systematic way: - * parameter retrieve_mode is bitwise or'ed of the ST_* flags. - * if res_inode is a NULL pointer, dont try to retrieve the last component - * at all. Parameters with prefix last_ are used only if res_inode is - * non-NULL and refer to the last component of the path only. +/* + * Name resolution. + * + * This is the basic name resolution function, turning a pathname + * into the final dentry. */ -int __namei(int retrieve_mode, const char * name, struct inode * base, - char * buf, struct inode ** res_dir, struct inode ** res_inode, - struct qstr * last_name, struct dentry ** last_entry, - int * last_error) -{ - char c; - struct qstr this; - char * linkname = NULL; - char * oldlinkname = NULL; - int trail_flag = 0; - int loopcount = 0; - int error; -#ifdef DEBUG - if(last_name) { - last_name->name = "(Uninitialized)"; - last_name->len = 15; - } -#endif -again: - error = -ENOENT; - this.name = name; - if (this.name[0] == '/') { - if(base) - iput(base); - if (__prefix_namei(retrieve_mode, this.name, base, buf, - res_dir, res_inode, - last_name, last_entry, last_error) == 0) - return 0; - base = current->fs->root; - atomic_inc(&base->i_count); - this.name++; +struct dentry * lookup_dentry(const char * name, struct dentry * base, int follow_link) +{ + struct dentry * dentry; + + if (*name == '/') { + if (base) + dput(base); + base = dget(current->fs->root); + do { + name++; + } while (*name == '/'); } else if (!base) { - base = current->fs->pwd; - atomic_inc(&base->i_count); + base = dget(current->fs->pwd); } + + if (*name == '\0') + return base; + + /* At this point we know we have a real path component. */ for(;;) { - struct inode * inode; - const char * tmp = this.name; int len; + unsigned long hash; + struct qstr this; + char c, trailing; + + this.name = name; + hash = init_name_hash(); + for (len = 0; (c = *name++) && (c != '/') ; len++) + hash = partial_name_hash(c, hash); - for(len = 0; (c = *tmp++) && (c != '/'); len++) ; this.len = len; - if(!c) - break; - while((c = *tmp) == '/') /* remove embedded/trailing slashes */ - tmp++; - if(!c) { - trail_flag = 1; - if(retrieve_mode & NAM_NO_TRAILSLASH) { - error = -EISDIR; - goto alldone; - } - break; - } -#if 0 - if(atomic_read(&base->i_count) == 0) - printk("vor lookup this=%s tmp=%s\n", this.name, tmp); -#endif - error = lookup(base, &this, 0, buf, NULL, NULL, &inode); -#if 0 - if(atomic_read(&base->i_count) == 0) - printk("nach lookup this=%s tmp=%s\n", this.name, tmp); -#endif - if (error) - goto alldone; - if(S_ISLNK(inode->i_mode)) { - error = _read_link(inode, &linkname, loopcount); - if(error) - goto alldone; - current->link_count++; - error = __namei((retrieve_mode & - ~(NAM_SEMLOCK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH)) - | NAM_FOLLOW_LINK, - linkname, base, buf, - &base, &inode, NULL, NULL, NULL); - current->link_count--; - if(error) - goto alldone; - } -#if 0 - if(atomic_read(&base->i_count) == 0) - printk("this=%s tmp=%s\n", this.name, tmp); -#endif - this.name = tmp; - iput(base); - base = inode; - } - if(res_inode) { - if(retrieve_mode & NAM_SEMLOCK) - down(&base->i_sem); - error = lookup(base, &this, retrieve_mode & NAM_TRANSCREATE, - buf, last_name, last_entry, res_inode); - if(!error && S_ISLNK((*res_inode)->i_mode) && - ((retrieve_mode & NAM_FOLLOW_LINK) || - (trail_flag && (retrieve_mode & NAM_FOLLOW_TRAILSLASH)))) { - char * tmp; - - error = _read_link(*res_inode, &linkname, loopcount); - if(error) - goto lastdone; - if(retrieve_mode & NAM_SEMLOCK) - up(&base->i_sem); - /* exchange pages */ - name = tmp = linkname; - linkname = oldlinkname; oldlinkname = tmp; - loopcount++; - goto again; /* Tail recursion elimination "by hand", - * uses less dynamic memory. - */ - - /* Note that trail_flag is not reset, so it - * does not matter in a symlink chain where a - * trailing slash indicates a directory endpoint. - */ - } - if(!error && trail_flag && !S_ISDIR((*res_inode)->i_mode)) { - iput(*res_inode); - error = -ENOTDIR; + this.hash = end_name_hash(hash); + + /* remove trailing slashes? */ + trailing = c; + if (c) { + while ((c = *name) == '/') + name++; } - lastdone: - if(last_error) { - *last_error = error; - error = 0; + + dentry = lookup(base, &this); + if (IS_ERR(dentry)) + break; + if (dentry->d_flag & D_NEGATIVE) + break; + + /* Last component? */ + if (!c) { + if (!trailing && !follow_link) + break; + return do_follow_link(base, dentry); } + + base = do_follow_link(base, dentry); } -alldone: - if(!error && res_dir) - *res_dir = base; - else - iput(base); - putname(linkname); - putname(oldlinkname); - return error; + dput(base); + return dentry; } /* @@ -641,26 +442,55 @@ * is used by most simple commands to get the inode of a specified name. * Open, link etc use their own routines, but this is enough for things * like 'chmod' etc. + * + * namei exists in two versions: namei/lnamei. The only difference is + * that namei follows links, while lnamei does not. */ - -/* [Feb 1997 T.Schoebel-Theuer] lnamei() completely removed; can be - * simulated when calling with retrieve_mode==NAM_FOLLOW_TRAILSLASH. - */ -int namei(int retrieve_mode, const char *pathname, struct inode **res_inode) +int __namei(const char *pathname, struct inode **res_inode, int follow_link) { int error; - char * tmp; + char * name; - error = getname(pathname, &tmp); + error = getname(pathname, &name); if (!error) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - error = __namei(retrieve_mode, tmp, NULL, - buf, NULL, res_inode, NULL, NULL, NULL); - putname(tmp); + struct dentry * dentry; + + dentry = lookup_dentry(name, NULL, follow_link); + putname(name); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = -ENOENT; + if (dentry) { + if (!(dentry->d_flag & D_NEGATIVE)) { + struct inode *inode = dentry->u.d_inode; + atomic_inc(&inode->i_count); + *res_inode = inode; + error = 0; + } + } + dput(dentry); + } } return error; } +static inline struct inode *get_parent(struct dentry *dentry) +{ + struct inode *dir = dentry->d_parent->u.d_inode; + + atomic_inc(&dir->i_count); + return dir; +} + +static inline struct inode *lock_parent(struct dentry *dentry) +{ + struct inode *dir = dentry->d_parent->u.d_inode; + + atomic_inc(&dir->i_count); + down(&dir->i_sem); + return dir; +} + /* * open_namei() * @@ -675,172 +505,155 @@ * for symlinks (where the permissions are checked later). */ int open_namei(const char * pathname, int flag, int mode, - struct inode ** res_inode, struct inode * base) + struct inode ** res_inode, struct dentry * base) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; int error; - int lasterror; - struct inode * dir, * inode; - int namei_mode; + struct inode *inode; + struct dentry *dentry; mode &= S_IALLUGO & ~current->fs->umask; mode |= S_IFREG; - namei_mode = NAM_FOLLOW_LINK; - if(flag & O_CREAT) - namei_mode |= NAM_SEMLOCK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH; - error = __namei(namei_mode, pathname, base, buf, - &dir, &inode, &last, NULL, &lasterror); - if (error) - goto exit; - error = lasterror; + dentry = lookup_dentry(pathname, base, 1); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + if (flag & O_CREAT) { - if (!error) { - if (flag & O_EXCL) { + struct inode *dir; + + dir = lock_parent(dentry); + /* + * The existence test must be done _after_ getting the directory + * semaphore - the dentry might otherwise change. + */ + if (!(dentry->d_flag & D_NEGATIVE)) { + error = 0; + if (flag & O_EXCL) error = -EEXIST; - } } else if (IS_RDONLY(dir)) error = -EROFS; else if (!dir->i_op || !dir->i_op->create) error = -EACCES; - else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - ; /* error is already set! */ - else { - d_del(d_lookup(dir, &last, NULL), D_REMOVE); - atomic_inc(&dir->i_count); /* create eats the dir */ + else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) == 0) { if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - error = dir->i_op->create(dir, last.name, last.len, - mode, res_inode); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(dir->i_dentry, NULL, &last, - " c %ld %d ", CURRENT_TIME, mode); -#endif - up(&dir->i_sem); - goto exit_dir; + error = dir->i_op->create(dir, dentry, mode); } up(&dir->i_sem); + iput(dir); + if (error) + goto exit; } + + error = -ENOENT; + if (dentry->d_flag & D_NEGATIVE) + goto exit; + + inode = dentry->u.d_inode; + error = -EISDIR; + if (S_ISDIR(inode->i_mode) && (flag & 2)) + goto exit; + + error = permission(inode,ACC_MODE(flag)); if (error) - goto exit_inode; + goto exit; - if (S_ISDIR(inode->i_mode) && (flag & 2)) { - error = -EISDIR; - goto exit_inode; - } - if ((error = permission(inode,ACC_MODE(flag))) != 0) { - goto exit_inode; - } + /* + * FIFO's, sockets and device files are special: they don't + * actually live on the filesystem itself, and as such you + * can write to them even if the filesystem is read-only. + */ if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - /* - * 2-Feb-1995 Bruce Perens - * Allow opens of Unix domain sockets and FIFOs for write on - * read-only filesystems. Their data does not live on the disk. - * - * If there was something like IS_NODEV(inode) for - * pipes and/or sockets I'd check it here. - */ flag &= ~O_TRUNC; - } - else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { - if (IS_NODEV(inode)) { - error = -EACCES; - goto exit_inode; - } + } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { + error = -EACCES; + if (IS_NODEV(inode)) + goto exit; + flag &= ~O_TRUNC; } else { - if (IS_RDONLY(inode) && (flag & 2)) { - error = -EROFS; - goto exit_inode; - } + error = -EROFS; + if (IS_RDONLY(inode) && (flag & 2)) + goto exit; } /* * An append-only file must be opened in append mode for writing. */ - if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) { - error = -EPERM; - goto exit_inode; - } + error = -EPERM; + if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) + goto exit; + if (flag & O_TRUNC) { - if ((error = get_write_access(inode))) - goto exit_inode; + error = get_write_access(inode); + if (error) + goto exit; + /* * Refuse to truncate files with mandatory locks held on them. */ error = locks_verify_locked(inode); - if (error) - goto exit_inode; - if (inode->i_sb && inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize(inode, -1); + if (!error) { + if (inode->i_sb && inode->i_sb->dq_op) + inode->i_sb->dq_op->initialize(inode, -1); - error = do_truncate(inode, 0); + error = do_truncate(inode, 0); + } put_write_access(inode); + if (error) + goto exit; } else if (flag & FMODE_WRITE) if (inode->i_sb && inode->i_sb->dq_op) inode->i_sb->dq_op->initialize(inode, -1); -exit_inode: - if(error) { - if(!lasterror) - iput(inode); - } else - *res_inode = inode; -exit_dir: - iput(dir); + + *res_inode = inode; + atomic_inc(&inode->i_count); + error = 0; + exit: + dput(dentry); return error; } int do_mknod(const char * filename, int mode, dev_t dev) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; - int error, lasterror; - struct inode * dir; - struct inode * inode; + int error; + struct inode *dir; + struct dentry *dentry; mode &= ~current->fs->umask; - error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE|NAM_NO_TRAILSLASH, - filename, NULL, buf, - &dir, &inode, &last, NULL, &lasterror); - if (error) + dentry = lookup_dentry(filename, NULL, 1); + + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto exit; - if(!lasterror) { - error = -EEXIST; - goto exit_inode; - } - if (!last.len) { - error = -ENOENT; - goto exit_inode; - } - if (IS_RDONLY(dir)) { - error = -EROFS; - goto exit_inode; - } - if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - goto exit_inode; - if (!dir->i_op || !dir->i_op->mknod) { - error = -ENOSYS; /* instead of EPERM, what does Posix say? */ - goto exit_inode; - } - atomic_inc(&dir->i_count); + + dir = lock_parent(dentry); + + error = -EEXIST; + if (!(dentry->d_flag & D_NEGATIVE)) + goto exit_lock; + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + error = permission(dir,MAY_WRITE | MAY_EXEC); + if (error) + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->mknod) + goto exit_lock; + if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - down(&dir->i_sem); - d_del(d_lookup(dir, &last, NULL), D_REMOVE); - error = dir->i_op->mknod(dir, last.name, last.len, mode, dev); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(dir->i_dentry, NULL, &last, " n %ld %d %d ", - CURRENT_TIME, mode, dev); -#endif + error = dir->i_op->mknod(dir, dentry, mode, dev); + +exit_lock: up(&dir->i_sem); -exit_inode: - if(!lasterror) - iput(inode); iput(dir); + dput(dentry); exit: return error; } @@ -874,58 +687,48 @@ return error; } -/* [Feb-97 T. Schoebel-Theuer] remove_trailing_slashes() is now obsolete, - * its functionality is handled by observing trailing slashes in __namei(). +/* + * Look out: this function may change a normal dentry + * into a directory dentry (different size).. */ static inline int do_mkdir(const char * pathname, int mode) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; - int error, lasterror; - struct inode * dir; - struct inode * inode; + int error; + struct inode *dir; + struct dentry *dentry; - mode &= 0777 & ~current->fs->umask; + dentry = lookup_dentry(pathname, NULL, 1); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto exit; + + dir = lock_parent(dentry); - error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, pathname, NULL, buf, - &dir, &inode, &last, NULL, &lasterror); + error = -EEXIST; + if (!(dentry->d_flag & D_NEGATIVE)) + goto exit_lock; + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + error = permission(dir,MAY_WRITE | MAY_EXEC); if (error) - goto exit; - if(!lasterror) { - error = -EEXIST; - goto exit_inode; - } - if (!last.len) { - error = -ENOENT; - goto exit_inode; - } - if (IS_RDONLY(dir)) { - error = -EROFS; - goto exit_inode; - } - if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - goto exit_inode; - if (!dir->i_op || !dir->i_op->mkdir) { - error = -ENOSYS; /* instead of EPERM, what does Posix say? */ - goto exit_inode; - } - atomic_inc(&dir->i_count); + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->mkdir) + goto exit_lock; + if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - down(&dir->i_sem); - d_del(d_lookup(dir, &last, NULL), D_REMOVE); - mode &= 01777 & ~current->fs->umask; - error = dir->i_op->mkdir(dir, last.name, last.len, mode); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(dir->i_dentry, NULL, &last, " d %ld %d ", - CURRENT_TIME, mode); -#endif + mode &= 0777 & ~current->fs->umask; + error = dir->i_op->mkdir(dir, dentry, mode); + +exit_lock: up(&dir->i_sem); -exit_inode: - if(!lasterror) - iput(inode); iput(dir); + dput(dentry); exit: return error; } @@ -945,124 +748,55 @@ return error; } -#if 0 /* We need a "deletefs", someone please write it. -DaveM */ -/* Perhaps this could be moved out into a new file. */ -static void basket_name(struct inode * dir, struct dentry * entry) -{ - char prefix[32]; - struct qstr prename = { prefix, 14 }; - struct qstr entname = { entry->d_name, entry->d_len }; - struct inode * inode; - struct dentry * old = entry; /* dummy */ - int i; - if(!entry || !(inode = d_inode(&entry))) - return; -#if 0 - if(atomic_read(&inode->i_count) > 2) { - extern void printpath(struct dentry *entry); - - printk("Caution: in use "); - if(inode->i_dentry) - printpath(inode->i_dentry); - printk(" i_nlink=%d i_count=%d i_ddir_count=%d i_dent_count=%d\n", - inode->i_nlink, atomic_read(&inode->i_count), - inode->i_ddir_count, inode->i_dent_count); - } -#endif - vfs_lock(); - for(i = 1; old; i++) { - sprintf(prefix, ".deleted-%04d.", i); - old = d_lookup(dir, &prename, &entname); - } - d_move(entry, dir, &prename, &entname); - vfs_unlock(); - iput(inode); -} -#endif - static inline int do_rmdir(const char * name) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; - struct dentry * lastent = NULL; int error; - struct inode * dir; - struct inode * inode; + struct inode *dir; + struct dentry *dentry; - /* [T.Schoebel-Theuer] I'm not sure which flags to use here. - * Try the following on different platforms: - * [0] rm -rf test test2 - * [1] ln -s test2 test - * [2] mkdir test || mkdir test2 - * [3] rmdir test && mkdir test2 - * [4] rmdir test/ - * Now the rusults: - * cmd | HP-UX | SunOS | Solaris | Old Linux | New Linux | - * ---------------------------------------------------------------- - * [2] | (OK) | EEXIST | EEXIST | EEXIST | (OK) - * [3] | ENOTDIR | ENOTDIR | ENOTDIR | ENOTDIR | ENOTDIR - * [4] | (OK) | EINVAL | ENOTDIR | ENOTDIR | (OK) - * So I implemented the HP-UX semantics. If this is not right - * for Posix compliancy, change the flags accordingly. If Posix - * let the question open, I'd suggest to stay at the new semantics. - * I'd even make case [3] work by adding 2 to the flags parameter - * if Posix tolerates that. - */ - error = __namei(NAM_FOLLOW_TRAILSLASH, name, NULL, buf, - &dir, &inode, &last, &lastent, NULL); - if (error) + dentry = lookup_dentry(name, NULL, 1); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto exit; - if (IS_RDONLY(dir)) { - error = -EROFS; - goto exit_dir; - } - if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - goto exit_dir; + + dir = lock_parent(dentry); + error = -ENOENT; + if (dentry->d_flag & D_NEGATIVE) + goto exit_lock; + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + error = permission(dir,MAY_WRITE | MAY_EXEC); + if (error) + goto exit_lock; + /* * A subdirectory cannot be removed from an append-only directory. */ - if (IS_APPEND(dir)) { - error = -EPERM; - goto exit_dir; - } - if (!dir->i_op || !dir->i_op->rmdir) { - error = -ENOSYS; /* was EPERM */ - goto exit_dir; - } + error = -EPERM; + if (IS_APPEND(dir)) + goto exit_lock; + /* Disallow removals of mountpoints. */ - if(inode->i_mount) { - error = -EBUSY; - goto exit_dir; - } + error = -EBUSY; + if (dentry->d_covers != dentry) + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->rmdir) + goto exit_lock; + if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - down(&dir->i_sem); -#if 0 - if(lastent && d_isbasket(lastent)) { - d_del(lastent, D_REMOVE); - error = 0; - goto exit_lock; - } -#endif - atomic_inc(&dir->i_count); - error = dir->i_op->rmdir(dir, last.name, last.len); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(lastent, NULL, NULL, " r %ld ", CURRENT_TIME); -#endif -#if 0 - if(!error && lastent) - basket_name(dir, lastent); + error = dir->i_op->rmdir(dir, dentry); + exit_lock: -#else - if(!error && lastent) - d_del(lastent, D_REMOVE); -#endif up(&dir->i_sem); -exit_dir: - iput(inode); - iput(dir); + iput(dir); + dput(dentry); exit: return error; } @@ -1084,90 +818,45 @@ static inline int do_unlink(const char * name) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; - struct dentry * lastent = NULL; int error; - struct inode * dir; - struct inode * inode; + struct inode *dir; + struct dentry *dentry; - /* HP-UX shows a strange behaviour: - * touch y; ln -s y x; rm x/ - * this succeeds and removes the file y, not the symlink x! - * Solaris and old Linux remove the symlink instead, and - * old SunOS complains ENOTDIR. - * I chose the SunOS behaviour (by not using NAM_FOLLOW_TRAILSLASH), - * but I'm not shure whether I should. - * The current code generally prohibits using trailing slashes with - * non-directories if the name already exists, but not if - * it is to be newly created. - * Perhaps this should be further strengthened (by introducing - * an additional flag bit indicating whether trailing slashes are - * allowed) to get it as consistant as possible, but I don't know - * what Posix says. - */ - error = __namei(NAM_NO_TRAILSLASH, name, NULL, buf, - &dir, &inode, &last, &lastent, NULL); - if (error) + dentry = lookup_dentry(name, NULL, 0); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto exit; - if (IS_RDONLY(dir)) { - error = -EROFS; - goto exit_dir; - } - if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - goto exit_dir; + + dir = lock_parent(dentry); + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + error = permission(dir,MAY_WRITE | MAY_EXEC); + if (error) + goto exit_lock; + /* * A file cannot be removed from an append-only directory. */ - if (IS_APPEND(dir)) { - error = -EPERM; - goto exit_dir; - } - if (!dir->i_op || !dir->i_op->unlink) { - error = -ENOSYS; /* was EPERM */ - goto exit_dir; - } + error = -EPERM; + if (IS_APPEND(dir)) + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->unlink) + goto exit_lock; + if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - down(&dir->i_sem); -#if 0 - if(atomic_read(&inode->i_count) > 1) { - extern void printpath(struct dentry *entry); - - printk("Fire "); - if(lastent) - printpath(lastent); - printk(" i_nlink=%d i_count=%d i_ddir_count=%d i_dent_count=%d\n", - inode->i_nlink, atomic_read(&inode->i_count), - inode->i_ddir_count, inode->i_dent_count); - } -#endif -#if 0 - if(lastent && d_isbasket(lastent)) { - d_del(lastent, D_REMOVE); - error = 0; - goto exit_lock; - } -#endif - atomic_inc(&dir->i_count); - error = dir->i_op->unlink(dir, last.name, last.len); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(lastent, NULL, NULL, " u %ld ", CURRENT_TIME); -#endif -#if 0 - if(!error && lastent) - basket_name(dir, lastent); + error = dir->i_op->unlink(dir, dentry); + exit_lock: -#else - if(!error && lastent) - d_del(lastent, D_REMOVE); -#endif up(&dir->i_sem); -exit_dir: - iput(inode); - iput(dir); + iput(dir); + dput(dentry); exit: return error; } @@ -1189,62 +878,42 @@ static inline int do_symlink(const char * oldname, const char * newname) { - char buf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr last; - int error, lasterror; - struct inode * dir; - struct inode * inode; - - /* The following works on HP-UX and Solaris, by producing - * a symlink chain: - * rm -rf ? ; mkdir z ; ln -s z y ; ln -s y x/ - * Under old SunOS, the following occurs: - * ln: x/: No such file or directory - * Under old Linux, very strange things occur: - * ln: cannot create symbolic link `x//y' to `y': No such file or directory - * This is very probably a bug, but may be caused by the ln program - * when checking for a directory target. - * - * I'm not shure whether to add NAM_NO_TRAILSLASH to inhibit trailing - * slashes in the target generally. - */ - error = __namei(NAM_TRANSCREATE, newname, NULL, buf, - &dir, &inode, &last, NULL, &lasterror); - if (error) + int error; + struct inode *dir; + struct dentry *dentry; + + dentry = lookup_dentry(newname, NULL, 0); + + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto exit; - if(!lasterror) { - iput(inode); - error = -EEXIST; - goto exit_dir; - } - if (!last.len) { - error = -ENOENT; - goto exit_dir; - } - if (IS_RDONLY(dir)) { - error = -EROFS; - goto exit_dir; - } - if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) - goto exit_dir; - if (!dir->i_op || !dir->i_op->symlink) { - error = -ENOSYS; /* was EPERM */ - goto exit_dir; - } - atomic_inc(&dir->i_count); + + error = -EEXIST; + if (!(dentry->d_flag & D_NEGATIVE)) + goto exit; + + dir = lock_parent(dentry); + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + error = permission(dir,MAY_WRITE | MAY_EXEC); + if (error) + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->symlink) + goto exit_lock; + if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); - down(&dir->i_sem); - d_del(d_lookup(dir, &last, NULL), D_REMOVE); - error = dir->i_op->symlink(dir, last.name, last.len, oldname); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(dir->i_dentry, NULL, &last, - " s %ld %s\0", CURRENT_TIME, oldname); -#endif + error = dir->i_op->symlink(dir, dentry, oldname); + +exit_lock: up(&dir->i_sem); -exit_dir: iput(dir); + dput(dentry); exit: return error; } @@ -1270,73 +939,60 @@ static inline int do_link(const char * oldname, const char * newname) { - char oldbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - char newbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr oldlast; - struct qstr newlast; - struct dentry * oldent = NULL; - struct inode * oldinode; - struct inode * newinode; - struct inode * newdir; - int error, lasterror; - - error = __namei(NAM_FOLLOW_LINK|NAM_NO_TRAILSLASH, - oldname, NULL, oldbuf, - NULL, &oldinode, &oldlast, &oldent, NULL); - if (error) + struct dentry *old_dentry, *new_dentry; + struct inode *dir, *oldinode; + int error; + + old_dentry = lookup_dentry(oldname, NULL, 1); + error = PTR_ERR(old_dentry); + if (IS_ERR(old_dentry)) goto exit; - error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, newname, NULL, newbuf, - &newdir, &newinode, &newlast, NULL, &lasterror); + new_dentry = lookup_dentry(oldname, NULL, 1); + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) + goto exit_old; + + dir = lock_parent(new_dentry); + + error = -ENOENT; + if (old_dentry->d_flag & D_NEGATIVE) + goto exit_lock; + + error = -EROFS; + if (IS_RDONLY(dir)) + goto exit_lock; + + oldinode = old_dentry->u.d_inode; + error = -EXDEV; + if (dir->i_dev != oldinode->i_dev) + goto exit_lock; + + error = permission(dir, MAY_WRITE | MAY_EXEC); if (error) - goto old_exit; - if(!lasterror) { - iput(newinode); - error = -EEXIST; - goto new_exit; - } - if (!newlast.len) { - error = -EPERM; - goto new_exit; - } - if (IS_RDONLY(newdir)) { - error = -EROFS; - goto new_exit; - } - if (newdir->i_dev != oldinode->i_dev) { - error = -EXDEV; - goto new_exit; - } - if ((error = permission(newdir,MAY_WRITE | MAY_EXEC)) != 0) - goto new_exit; + goto exit_lock; + /* * A link to an append-only or immutable file cannot be created. */ - if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) { - error = -EPERM; - goto new_exit; - } - if (!newdir->i_op || !newdir->i_op->link) { - error = -ENOSYS; /* was EPERM */ - goto new_exit; - } - atomic_inc(&oldinode->i_count); - atomic_inc(&newdir->i_count); - if (newdir->i_sb && newdir->i_sb->dq_op) - newdir->i_sb->dq_op->initialize(newdir, -1); - down(&newdir->i_sem); - d_del(d_lookup(newdir, &newlast, NULL), D_REMOVE); - error = newdir->i_op->link(oldinode, newdir, newlast.name, newlast.len); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(oldent, newdir->i_dentry, &newlast, - " l %ld ", CURRENT_TIME); -#endif - up(&newdir->i_sem); -new_exit: - iput(newdir); -old_exit: - iput(oldinode); + error = -EPERM; + if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) + goto exit_lock; + + error = -EPERM; + if (!dir->i_op || !dir->i_op->link) + goto exit_lock; + + if (dir->i_sb && dir->i_sb->dq_op) + dir->i_sb->dq_op->initialize(dir, -1); + error = dir->i_op->link(oldinode, dir, new_dentry); + +exit_lock: + up(&dir->i_sem); + iput(dir); + dput(new_dentry); +exit_old: + dput(old_dentry); exit: return error; } @@ -1360,105 +1016,99 @@ return error; } +/* + * Whee.. Deadlock country. Happily there is only one VFS + * operation that does this.. + */ +static inline void double_down(struct semaphore *s1, struct semaphore *s2) +{ + if ((unsigned long) s1 < (unsigned long) s2) { + down(s1); + down(s2); + } else if (s1 == s2) { + down(s1); + atomic_dec(&s1->count); + } else { + down(s2); + down(s1); + } +} + static inline int do_rename(const char * oldname, const char * newname) { - char oldbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr oldlast; - char newbuf[MAX_TRANS_FILELEN+MAX_TRANS_SUFFIX+2]; - struct qstr newlast; - struct dentry * oldent = NULL; - struct inode * olddir, * newdir; - struct inode * oldinode, * newinode; - int error, newlasterror; + int error; + struct inode * old_dir, * new_dir; + struct dentry * old_dentry, *new_dentry; - error = __namei(NAM_FOLLOW_TRAILSLASH, oldname, NULL, oldbuf, - &olddir, &oldinode, &oldlast, &oldent, NULL); - if (error) + old_dentry = lookup_dentry(oldname, NULL, 1); + + error = PTR_ERR(old_dentry); + if (IS_ERR(old_dentry)) goto exit; - if ((error = permission(olddir,MAY_WRITE | MAY_EXEC)) != 0) - goto old_exit; - if (!oldlast.len || (oldlast.name[0] == '.' && - (oldlast.len == 1 || (oldlast.name[1] == '.' && - oldlast.len == 2)))) { - error = -EPERM; - goto old_exit; - } + + new_dentry = lookup_dentry(newname, NULL, 1); + + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) + goto exit_old; + + new_dir = get_parent(new_dentry); + old_dir = get_parent(old_dentry); + + double_down(&new_dir->i_sem, &old_dir->i_sem); + + error = -ENOENT; + if (new_dentry->d_flag & D_NEGATIVE) + goto exit_lock; + + error = permission(old_dir,MAY_WRITE | MAY_EXEC); + if (error) + goto exit_lock; + + error = -EPERM; + if (is_reserved(new_dentry) || is_reserved(old_dentry)) + goto exit_lock; + /* Disallow moves of mountpoints. */ - if(oldinode->i_mount) { - error = -EBUSY; - goto old_exit; - } + error = -EBUSY; + if (old_dentry->d_covers != old_dentry) + goto exit_lock; - error = __namei(NAM_FOLLOW_LINK|NAM_TRANSCREATE, newname, NULL, newbuf, - &newdir, &newinode, &newlast, NULL, &newlasterror); + error = permission(new_dir,MAY_WRITE | MAY_EXEC); if (error) - goto old_exit; - if ((error = permission(newdir,MAY_WRITE | MAY_EXEC)) != 0) - goto new_exit; - if (!newlast.len || (newlast.name[0] == '.' && - (newlast.len == 1 || (newlast.name[1] == '.' && - newlast.len == 2)))) { - error = -EPERM; - goto new_exit; - } - if (newdir->i_dev != olddir->i_dev) { - error = -EXDEV; - goto new_exit; - } - if (IS_RDONLY(newdir) || IS_RDONLY(olddir)) { - error = -EROFS; - goto new_exit; - } + goto exit_lock; + + error = -EXDEV; + if (new_dir->i_dev != old_dir->i_dev) + goto exit_lock; + + error = -EROFS; + if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) + goto exit_lock; + /* * A file cannot be removed from an append-only directory. */ - if (IS_APPEND(olddir)) { - error = -EPERM; - goto new_exit; - } - if (!olddir->i_op || !olddir->i_op->rename) { - error = -ENOSYS; /* was EPERM */ - goto new_exit; - } -#ifdef CONFIG_TRANS_NAMES - /* if oldname has been translated, but newname not (and - * has not already a suffix), take over the suffix from oldname. - */ - if(oldlast.name == oldbuf && newlast.name != newbuf && - newlast.name[newlast.len-1] != '#') { - int i = oldlast.len - 2; - while (i > 0 && oldlast.name[i] != '#') - i--; - memcpy(newbuf, newlast.name, newlast.len); - memcpy(newbuf+newlast.len, oldlast.name+i, oldlast.len - i); - newlast.len += oldlast.len - i; - newlast.name = newbuf; - } -#endif - atomic_inc(&olddir->i_count); - atomic_inc(&newdir->i_count); - if (newdir->i_sb && newdir->i_sb->dq_op) - newdir->i_sb->dq_op->initialize(newdir, -1); - down(&newdir->i_sem); - error = olddir->i_op->rename(olddir, oldlast.name, oldlast.len, - newdir, newlast.name, newlast.len); -#ifdef CONFIG_OMIRR - if(!error) - omirr_print(oldent, newdir->i_dentry, &newlast, - " m %ld ", CURRENT_TIME); -#endif - if(!error) { - d_del(d_lookup(newdir, &newlast, NULL), D_REMOVE); - d_move(d_lookup(olddir, &oldlast, NULL), newdir, &newlast, NULL); - } - up(&newdir->i_sem); -new_exit: - if(!newlasterror) - iput(newinode); - iput(newdir); -old_exit: - iput(oldinode); - iput(olddir); + error = -EPERM; + if (IS_APPEND(old_dir)) + goto exit_lock; + + error = -EPERM; + if (!old_dir->i_op || !old_dir->i_op->rename) + goto exit_lock; + + if (new_dir->i_sb && new_dir->i_sb->dq_op) + new_dir->i_sb->dq_op->initialize(new_dir, -1); + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + +exit_lock: + up(&new_dir->i_sem); + up(&old_dir->i_sem); + iput(old_dir); + iput(new_dir); + dput(new_dentry); +exit_old: + dput(old_dentry); exit: return error; } diff -u --recursive --new-file v2.1.43/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.1.43/linux/fs/ncpfs/inode.c Mon Jun 16 16:35:58 1997 +++ linux/fs/ncpfs/inode.c Thu Jun 26 12:33:39 1997 @@ -408,7 +408,7 @@ static struct file_system_type ncp_fs_type = { "ncpfs", - FS_NO_DCACHE, + 0 /* FS_NO_DCACHE doesn't work correctly */, ncp_read_super, NULL }; diff -u --recursive --new-file v2.1.43/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.1.43/linux/fs/nfs/inode.c Mon Jun 16 16:35:58 1997 +++ linux/fs/nfs/inode.c Thu Jun 26 12:33:39 1997 @@ -435,7 +435,7 @@ */ static struct file_system_type nfs_fs_type = { "nfs", - FS_NO_DCACHE, + 0 /* FS_NO_DCACHE - this doesn't work right now*/, nfs_read_super, NULL }; diff -u --recursive --new-file v2.1.43/linux/fs/open.c linux/fs/open.c --- v2.1.43/linux/fs/open.c Mon Jun 16 16:35:58 1997 +++ linux/fs/open.c Tue Jul 1 14:06:58 1997 @@ -35,7 +35,7 @@ error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs)); if (error) goto out; - error = namei(NAM_FOLLOW_LINK, path, &inode); + error = namei(path, &inode); if (error) goto out; error = -ENOSYS; @@ -102,7 +102,7 @@ int error; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, path, &inode); + error = namei(path, &inode); if (error) goto out; @@ -189,7 +189,7 @@ lock_kernel(); /* Hmm, should I always follow symlinks or not ? */ - error = namei(NAM_FOLLOW_LINK, filename, &inode); + error = namei(filename, &inode); if (error) goto out; error = -EROFS; @@ -237,7 +237,7 @@ struct iattr newattrs; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, filename, &inode); + error = namei(filename, &inode); if (error) goto out; error = -EROFS; @@ -287,7 +287,7 @@ old_fsgid = current->fsgid; current->fsuid = current->uid; current->fsgid = current->gid; - res = namei(NAM_FOLLOW_LINK, filename, &inode); + res = namei(filename, &inode); if (!res) { res = permission(inode, mode); iput(inode); @@ -301,24 +301,37 @@ asmlinkage int sys_chdir(const char * filename) { - struct inode * inode; - struct inode * tmpi; int error; + struct inode *inode; + struct dentry *dentry, *tmp; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, filename, &inode); - if (error) + + dentry = lookup_dentry(filename, NULL, 1); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto out; + + error = -ENOENT; + if (dentry->d_flag & D_NEGATIVE) + goto dput_and_out; + error = -ENOTDIR; + inode = dentry->u.d_inode; if (!S_ISDIR(inode->i_mode)) - goto iput_and_out; - if ((error = permission(inode,MAY_EXEC)) != 0) - goto iput_and_out; + goto dput_and_out; - /* exchange inodes */ - tmpi = current->fs->pwd; current->fs->pwd = inode; inode = tmpi; -iput_and_out: - iput(inode); + error = permission(inode,MAY_EXEC); + if (error) + goto dput_and_out; + + /* exchange dentries */ + tmp = current->fs->pwd; + current->fs->pwd = dentry; + dentry = tmp; + +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -326,24 +339,33 @@ asmlinkage int sys_fchdir(unsigned int fd) { - struct inode * inode; - struct file * file; - int error = -EBADF; + struct file *file; + struct inode *inode; + struct dentry *dentry, *tmp; + int error; lock_kernel(); + + error = -EBADF; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) goto out; + error = -ENOENT; if (!(inode = file->f_inode)) goto out; + error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) goto out; - if ((error = permission(inode,MAY_EXEC)) != 0) + + error = permission(inode,MAY_EXEC); + if (error) goto out; - iput(current->fs->pwd); - current->fs->pwd = inode; - atomic_inc(&inode->i_count); + + dentry = dget(inode->i_dentry); + tmp = current->fs->pwd; + current->fs->pwd = dentry; + dput(tmp); out: unlock_kernel(); return error; @@ -351,24 +373,41 @@ asmlinkage int sys_chroot(const char * filename) { - struct inode * inode; - struct inode * tmpi; int error; + struct inode *inode; + struct dentry *dentry, *tmp; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, filename, &inode); - if (error) + + dentry = lookup_dentry(filename, NULL, 1); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto out; + + error = -ENOENT; + if (dentry->d_flag & D_NEGATIVE) + goto dput_and_out; + error = -ENOTDIR; + inode = dentry->u.d_inode; if (!S_ISDIR(inode->i_mode)) - goto iput_and_out; + goto dput_and_out; + + error = permission(inode,MAY_EXEC); + if (error) + goto dput_and_out; + error = -EPERM; if (!fsuser()) - goto iput_and_out; - tmpi = current->fs->root; current->fs->root = inode; inode = tmpi; - error = 0; -iput_and_out: - iput(inode); + goto dput_and_out; + + /* exchange dentries */ + tmp = current->fs->root; + current->fs->root = dentry; + dentry = tmp; + +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -419,7 +458,7 @@ * because permissions on symlinks now can never be changed, * but on the other hand they are never needed. */ - error = namei(NAM_FOLLOW_LINK, filename, &inode); + error = namei(filename, &inode); if (error) goto out; error = -EROFS; @@ -517,7 +556,7 @@ struct iattr newattrs; lock_kernel(); - error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode); + error = namei(filename, &inode); if (error) goto out; error = -EROFS; diff -u --recursive --new-file v2.1.43/linux/fs/proc/arbitrary.c linux/fs/proc/arbitrary.c --- v2.1.43/linux/fs/proc/arbitrary.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/arbitrary.c Sat Jul 5 20:53:22 1997 @@ -53,6 +53,5 @@ error = 0; } done: - iput(dir); return error; } diff -u --recursive --new-file v2.1.43/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.43/linux/fs/proc/array.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/array.c Sat Jul 5 20:53:22 1997 @@ -1216,6 +1216,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -1261,6 +1262,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/proc/base.c linux/fs/proc/base.c --- v2.1.43/linux/fs/proc/base.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/base.c Sat Jul 5 20:53:22 1997 @@ -42,6 +42,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.1.43/linux/fs/proc/fd.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/fd.c Sat Jul 5 20:53:22 1997 @@ -44,6 +44,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -65,24 +66,9 @@ if (!dir) return -ENOENT; sb = dir->i_sb; - if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode)) { - iput(dir); + if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode)) return -ENOENT; - } - if (!len || (name[0] == '.' && (len == 1 || - (name[1] == '.' && len == 2)))) { - if (len < 2) { - *result = dir; - return 0; - } - if (!(*result = proc_get_inode(sb, (pid << 16)+PROC_PID_INO, &proc_pid))) { - iput(dir); - return -ENOENT; - } - iput(dir); - return 0; - } - iput(dir); + fd = 0; while (len-- > 0) { c = *name - '0'; diff -u --recursive --new-file v2.1.43/linux/fs/proc/generic.c linux/fs/proc/generic.c --- v2.1.43/linux/fs/proc/generic.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/generic.c Sat Jul 5 20:53:22 1997 @@ -51,6 +51,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -73,6 +74,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.1.43/linux/fs/proc/inode.c Tue May 13 22:41:15 1997 +++ linux/fs/proc/inode.c Tue Jul 1 16:43:48 1997 @@ -131,12 +131,13 @@ s->s_magic = PROC_SUPER_MAGIC; s->s_op = &proc_sops; unlock_super(s); - if (!(s->s_mounted = proc_get_inode(s, PROC_ROOT_INO, &proc_root))) { + s->s_root = d_alloc_root(proc_get_inode(s, PROC_ROOT_INO, &proc_root), NULL); + if (!s->s_root) { s->s_dev = 0; printk("get root inode failed\n"); return NULL; } - parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid); + parse_options(data, &s->s_root->u.d_inode->i_uid, &s->s_root->u.d_inode->i_gid); return s; } diff -u --recursive --new-file v2.1.43/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c --- v2.1.43/linux/fs/proc/kmsg.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/kmsg.c Sat Jul 5 20:53:22 1997 @@ -70,6 +70,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.1.43/linux/fs/proc/link.c Mon Jun 16 16:35:58 1997 +++ linux/fs/proc/link.c Sat Jul 5 20:53:22 1997 @@ -17,6 +17,7 @@ #include static int proc_readlink(struct inode *, char *, int); +static struct dentry * proc_follow_link(struct inode *, struct dentry *); /* * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke @@ -52,6 +53,7 @@ NULL, /* mknod */ NULL, /* rename */ proc_readlink, /* readlink */ + proc_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -59,59 +61,52 @@ NULL /* permission */ }; -/* [Feb-1997 T. Schoebel-Theuer] This is no longer called from the - * VFS, but only from proc_readlink(). All the functionality - * should the moved there (without using temporary inodes any more) - * and then it could be eliminated. - */ -static int proc_follow_link(struct inode * dir, struct inode * inode, - int flag, int mode, struct inode ** res_inode) +static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base) { - unsigned int pid, ino; - struct task_struct * p; - struct inode * new_inode; + struct task_struct *p; + struct dentry * result; + int ino, pid; int error; - *res_inode = NULL; - if (dir) - iput(dir); - if (!inode) - return -ENOENT; - if ((error = permission(inode, MAY_EXEC)) != 0){ - iput(inode); - return error; - } + /* We don't need a base pointer in the /proc filesystem */ + dput(base); + + error = permission(inode, MAY_EXEC); + result = ERR_PTR(error); + if (error) + return result; + ino = inode->i_ino; pid = ino >> 16; ino &= 0x0000ffff; p = find_task_by_pid(pid); - if (!p) { - iput(inode); - return -ENOENT; - } - new_inode = NULL; + result = ERR_PTR(-ENOENT); + if (!p) + return result; + switch (ino) { case PROC_PID_CWD: - if (!p->fs) + if (!p->fs || !p->fs->pwd) break; - new_inode = p->fs->pwd; + result = dget(p->fs->pwd); break; + case PROC_PID_ROOT: - if (!p->fs) + if (!p->fs || !p->fs->root) break; - new_inode = p->fs->root; + result = dget(p->fs->root); break; + case PROC_PID_EXE: { struct vm_area_struct * vma; if (!p->mm) break; vma = p->mm->mmap; while (vma) { - if (vma->vm_flags & VM_EXECUTABLE) { - new_inode = vma->vm_inode; - break; - } + if (vma->vm_flags & VM_EXECUTABLE) + return dget(vma->vm_inode->i_dentry); + vma = vma->vm_next; } break; @@ -122,45 +117,38 @@ if (!p->files) break; ino &= 0xff; - if (ino < NR_OPEN && p->files->fd[ino]) { - new_inode = p->files->fd[ino]->f_inode; - } + if (ino >= NR_OPEN) + break; + if (!p->files->fd[ino]) + break; + if (!p->files->fd[ino]->f_inode) + break; + result = dget(p->files->fd[ino]->f_inode->i_dentry); break; } } - iput(inode); - if (!new_inode) - return -ENOENT; - *res_inode = new_inode; - atomic_inc(&new_inode->i_count); - return 0; + return result; } static int proc_readlink(struct inode * inode, char * buffer, int buflen) { - int error = proc_follow_link(NULL, inode, 0, 0, &inode); + int error; + struct dentry * dentry = proc_follow_link(inode, NULL); - if (error) - return error; - if (!inode) - return -EIO; - - /* This will return *one* of the alias names (which is not quite - * correct). I have to rethink the problem, so this is only a - * quick hack... - */ - if(inode->i_dentry) { - char * tmp = (char*)__get_free_page(GFP_KERNEL); - int len = d_path(inode->i_dentry, current->fs->root, tmp); - int min = buflenfs->root, tmp); + int min = buflenpid); if (buflen < len) len = buflen; @@ -358,6 +360,15 @@ return len; } +static struct dentry * proc_self_follow_link(struct inode *inode, struct dentry *base) +{ + int len; + char tmp[30]; + + len = sprintf(tmp, "%d", current->pid); + return lookup_dentry(tmp, base, 1); +} + static struct inode_operations proc_self_inode_operations = { NULL, /* no file-ops */ NULL, /* create */ @@ -370,6 +381,7 @@ NULL, /* mknod */ NULL, /* rename */ proc_self_readlink, /* readlink */ + proc_self_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -631,16 +643,12 @@ int ino; *result = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { - iput(dir); + if (!dir || !S_ISDIR(dir->i_mode)) return -ENOTDIR; - } de = (struct proc_dir_entry *) dir->u.generic_ip; - if (!de) { - iput(dir); + if (!de) return -EINVAL; - } /* Either remove this as soon as possible due to security problems, * or uncomment the root-only usage. @@ -652,41 +660,19 @@ if(/*!current->uid &&*/ name[0] == '[') return proc_arbitrary_lookup(dir,name,len,result); - /* Special case "." and "..": they aren't on the directory list */ - *result = dir; - if (!len) - return 0; - if (name[0] == '.') { - if (len == 1) - return 0; - if (name[1] == '.' && len == 2) { - struct inode * inode; - inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent); - iput(dir); - if (!inode) - return -EINVAL; - *result = inode; - return 0; - } - } - *result = NULL; for (de = de->subdir; de ; de = de->next) { if (proc_match(len, name, de)) break; } - if (!de) { - iput(dir); + if (!de) return -ENOENT; - } ino = de->low_ino | (dir->i_ino & ~(0xffff)); - if (!(*result = proc_get_inode(dir->i_sb, ino, de))) { - iput(dir); + + if (!(*result = proc_get_inode(dir->i_sb, ino, de))) return -EINVAL; - } - iput(dir); return 0; } @@ -711,10 +697,8 @@ } retval = proc_lookup(dir, name, len, result); - if (retval != -ENOENT) { - iput(dir); + if (retval != -ENOENT) return retval; - } pid = 0; while (len-- > 0) { @@ -732,16 +716,12 @@ } } p = find_task_by_pid(pid); - if (!pid || !p) { - iput(dir); + if (!pid || !p) return -ENOENT; - } + ino = (pid << 16) + PROC_PID_INO; - if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) { - iput(dir); + if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) return -EINVAL; - } - iput(dir); return 0; } diff -u --recursive --new-file v2.1.43/linux/fs/proc/scsi.c linux/fs/proc/scsi.c --- v2.1.43/linux/fs/proc/scsi.c Mon Jun 16 16:35:59 1997 +++ linux/fs/proc/scsi.c Sat Jul 5 20:53:22 1997 @@ -69,6 +69,7 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff -u --recursive --new-file v2.1.43/linux/fs/readdir.c linux/fs/readdir.c --- v2.1.43/linux/fs/readdir.c Mon Jun 16 16:35:59 1997 +++ linux/fs/readdir.c Thu Jun 26 12:33:39 1997 @@ -266,8 +266,8 @@ if(inode) { nr++; if(nr > (file->f_pos & ~BASKET_BIT)) { - int err = filldir(&buf, ptr->d_name, - ptr->d_len, + int err = filldir(&buf, ptr->d_name.name, + ptr->d_name.len, file->f_pos, inode->i_ino); if(err) diff -u --recursive --new-file v2.1.43/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.1.43/linux/fs/romfs/inode.c Mon Jun 16 16:35:59 1997 +++ linux/fs/romfs/inode.c Thu Jun 26 12:33:39 1997 @@ -584,7 +584,7 @@ static struct file_system_type romfs_fs_type = { "romfs", - (FS_REQUIRES_DEV | FS_NO_DCACHE), /* Can dcache be used? */ + FS_REQUIRES_DEV, romfs_read_super, NULL }; diff -u --recursive --new-file v2.1.43/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.43/linux/fs/smbfs/inode.c Mon Jun 16 16:35:59 1997 +++ linux/fs/smbfs/inode.c Thu Jun 26 12:33:39 1997 @@ -431,7 +431,7 @@ static struct file_system_type smb_fs_type = { "smbfs", - FS_NO_DCACHE, + 0 /* FS_NO_DCACHE doesn't work correctly */, smb_read_super, NULL }; diff -u --recursive --new-file v2.1.43/linux/fs/stat.c linux/fs/stat.c --- v2.1.43/linux/fs/stat.c Mon Jun 16 16:35:59 1997 +++ linux/fs/stat.c Sat Jul 5 20:53:22 1997 @@ -127,7 +127,7 @@ int error; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, filename, &inode); + error = namei(filename, &inode); if (error) goto out; if ((error = do_revalidate(inode)) == 0) @@ -145,7 +145,7 @@ int error; lock_kernel(); - error = namei(NAM_FOLLOW_LINK, filename, &inode); + error = namei(filename, &inode); if (error) goto out; if ((error = do_revalidate(inode)) == 0) @@ -168,7 +168,7 @@ int error; lock_kernel(); - error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode); + error = lnamei(filename, &inode); if (error) goto out; if ((error = do_revalidate(inode)) == 0) @@ -187,7 +187,7 @@ int error; lock_kernel(); - error = namei(NAM_FOLLOW_TRAILSLASH, filename, &inode); + error = lnamei(filename, &inode); if (error) goto out; if ((error = do_revalidate(inode)) == 0) @@ -249,7 +249,7 @@ error = verify_area(VERIFY_WRITE,buf,bufsiz); if (error) goto out; - error = namei(NAM_FOLLOW_TRAILSLASH, path, &inode); + error = lnamei(path, &inode); if (error) goto out; error = -EINVAL; @@ -263,6 +263,7 @@ inode->i_dirt = 1; } error = inode->i_op->readlink(inode,buf,bufsiz); + iput(inode); out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.43/linux/fs/super.c linux/fs/super.c --- v2.1.43/linux/fs/super.c Mon Jun 16 16:35:59 1997 +++ linux/fs/super.c Tue Jul 1 17:12:38 1997 @@ -465,7 +465,7 @@ } if (!(sb = get_super(dev))) return; - if (sb->s_covered) { + if (sb->s_root != sb->s_root->d_mounts) { printk("VFS: Mounted device %s - tssk, tssk\n", kdevname(dev)); return; @@ -535,7 +535,6 @@ return NULL; } s->s_dev = dev; - s->s_covered = NULL; s->s_rd_only = 0; s->s_dirt = 0; s->s_type = type; @@ -570,6 +569,30 @@ kdevname(dev)); } +static void d_umount(struct dentry *dentry) +{ + struct dentry * covers = dentry->d_covers; + + if (covers == dentry) { + printk("VFS: unmount - covers == dentry?\n"); + return; + } + covers->d_mounts = covers; + dentry->d_covers = dentry; + dput(covers); + dput(dentry); +} + +static void d_mount(struct dentry *covers, struct dentry *dentry) +{ + if (covers->d_mounts != covers) { + printk("VFS: mount - already mounted\n"); + return; + } + covers->d_mounts = dentry; + dentry->d_covers = covers; +} + static int do_umount(kdev_t dev,int unmount_root) { struct super_block * sb; @@ -597,28 +620,27 @@ } return 0; } - if (!(sb=get_super(dev)) || !(sb->s_covered)) + sb=get_super(dev); + if (!sb) return -ENOENT; - if (!sb->s_covered->i_mount) - printk("VFS: umount(%s): mounted inode has i_mount=NULL\n", - kdevname(dev)); - while(sb->s_ibasket) - free_ibasket(sb); - if(sb->s_mounted->i_dentry) - d_del(sb->s_mounted->i_dentry, D_NO_CLEAR_INODE); + /* * Before checking if the filesystem is still busy make sure the kernel * doesn't hold any quotafiles open on that device. If the umount fails * too bad there are no quotas running anymore. Turn them on again by hand. */ quota_off(dev, -1); - if (!fs_may_umount(dev, sb->s_mounted)) + if (!fs_may_umount(dev, sb->s_root)) return -EBUSY; - sb->s_covered->i_mount = NULL; - iput(sb->s_covered); - sb->s_covered = NULL; - iput(sb->s_mounted); - sb->s_mounted = NULL; + + /* Clear up the dcache tree. This should be cleaner.. */ + while (sb->s_ibasket) + free_ibasket(sb); + if (sb->s_root) + d_del(sb->s_root, D_NO_CLEAR_INODE); + + d_umount(sb->s_root); + sb->s_root = NULL; if (sb->s_op && sb->s_op->write_super && sb->s_dirt) sb->s_op->write_super(sb); put_super(dev); @@ -647,12 +669,7 @@ lock_kernel(); if (!suser()) goto out; - retval = namei(NAM_FOLLOW_LINK, name, &inode); - if (retval) { - retval = namei(NAM_FOLLOW_TRAILSLASH, name, &inode); - if (retval) - goto out; - } + retval = namei(name, &inode); if (S_ISBLK(inode->i_mode)) { dev = inode->i_rdev; retval = -EACCES; @@ -662,7 +679,7 @@ } } else { retval = -EINVAL; - if (!inode->i_sb || inode != inode->i_sb->s_mounted) { + if (!inode->i_sb || inode != inode->i_sb->s_root->u.d_inode) { iput(inode); goto out; } @@ -715,45 +732,44 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data) { - struct inode * dir_i = NULL; + struct dentry * dir_d = NULL; struct super_block * sb; struct vfsmount *vfsmnt; int error; - int override = 0; - - if(dir_name) { - char c; - get_user(c, dir_name); - override = (c == '!'); - } if (!(flags & MS_RDONLY) && dev && is_read_only(dev)) return -EACCES; /*flags |= MS_RDONLY;*/ - if(override) - dir_name++; - error = namei(NAM_FOLLOW_LINK, dir_name, &dir_i); - if (error) + + dir_d = lookup_dentry(dir_name, NULL, 1); + error = PTR_ERR(dir_d); + if (IS_ERR(dir_d)) return error; - if (!override && (atomic_read(&dir_i->i_count) != 1 || dir_i->i_mount)) { - iput(dir_i); + + if (dir_d->d_flag & D_NEGATIVE) { + dput(dir_d); + return -ENOENT; + } + + if (dir_d->d_covers != dir_d) { + dput(dir_d); return -EBUSY; } - if (!S_ISDIR(dir_i->i_mode)) { - iput(dir_i); + if (!S_ISDIR(dir_d->u.d_inode->i_mode)) { + dput(dir_d); return -ENOTDIR; } - if (!fs_may_mount(dev) && !override) { - iput(dir_i); + if (!fs_may_mount(dev)) { + dput(dir_d); return -EBUSY; } sb = read_super(dev,type,flags,data,0); if (!sb) { - iput(dir_i); + dput(dir_d); return -EINVAL; } - if (sb->s_covered) { - iput(dir_i); + if (sb->s_root->d_covers != sb->s_root) { + dput(dir_d); return -EBUSY; } vfsmnt = add_vfsmnt(dev, dev_name, dir_name); @@ -761,25 +777,8 @@ vfsmnt->mnt_sb = sb; vfsmnt->mnt_flags = flags; } - { - struct dentry * old = dir_i->i_dentry; - struct dentry * new; - vfs_lock(); - new = d_alloc(old->d_parent, old->d_len, 1); - if(new) { - struct qstr copy = { old->d_name, old->d_len }; - d_add(new, sb->s_mounted, ©, D_DUPLICATE); - vfs_unlock(); - } else { - printk("VFS: cannot setup dentry for mount\n"); - iput(dir_i); - return -ENOMEM; - } - vfs_unlock(); - } - sb->s_covered = dir_i; - dir_i->i_mount = sb->s_mounted; - return 0; /* we don't iput(dir_i) - see umount */ + d_mount(dir_d, sb->s_root); + return 0; /* we don't dput(dir) - see umount */ } @@ -820,10 +819,10 @@ struct inode *dir_i; int retval; - retval = namei(NAM_FOLLOW_LINK, dir, &dir_i); + retval = namei(dir, &dir_i); if (retval) return retval; - if (dir_i != dir_i->i_sb->s_mounted) { + if (dir_i != dir_i->i_sb->s_root->u.d_inode) { iput(dir_i); return -EINVAL; } @@ -912,7 +911,7 @@ t = fstype->name; fops = NULL; if ((fstype->fs_flags & FS_REQUIRES_DEV)) { - retval = namei(NAM_FOLLOW_LINK, dev_name, &inode); + retval = namei(dev_name, &inode); if (retval) goto out; retval = -ENOTBLK; @@ -982,7 +981,7 @@ struct file_system_type * fs_type; struct super_block * sb; struct vfsmount *vfsmnt; - struct inode * inode, * d_inode = NULL; + struct inode * d_inode = NULL; struct file filp; int retval; @@ -1001,15 +1000,11 @@ sb->s_dev = get_unnamed_dev(); sb->s_flags = root_mountflags & ~MS_RDONLY; if (nfs_root_mount(sb) >= 0) { - inode = sb->s_mounted; - atomic_add(3, &inode->i_count); - sb->s_covered = inode; sb->s_rd_only = 0; sb->s_dirt = 0; sb->s_type = fs_type; - current->fs->pwd = inode; - current->fs->root = inode; - (void)d_alloc_root(inode); + current->fs->root = dget(sb->s_root); + current->fs->pwd = dget(sb->s_root); ROOT_DEV = sb->s_dev; printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n"); vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/"); @@ -1066,15 +1061,9 @@ continue; sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1); if (sb) { - inode = sb->s_mounted; - - /* NOTE! it is logically used 4 times, not 1 */ - atomic_add(3, &inode->i_count); - sb->s_covered = inode; sb->s_flags = root_mountflags; - current->fs->pwd = inode; - current->fs->root = inode; - (void)d_alloc_root(inode); + current->fs->root = dget(sb->s_root); + current->fs->pwd = dget(sb->s_root); printk ("VFS: Mounted root (%s filesystem)%s.\n", fs_type->name, (sb->s_flags & MS_RDONLY) ? " readonly" : ""); @@ -1121,7 +1110,7 @@ do_mount_root(); old_fs = get_fs(); set_fs(get_ds()); - error = namei(NAM_FOLLOW_LINK, put_old, &inode); + error = namei(put_old, &inode); if (error) inode = NULL; set_fs(old_fs); if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount)) diff -u --recursive --new-file v2.1.43/linux/include/asm-alpha/ioctls.h linux/include/asm-alpha/ioctls.h --- v2.1.43/linux/include/asm-alpha/ioctls.h Sun Mar 24 02:09:36 1996 +++ linux/include/asm-alpha/ioctls.h Thu Jun 26 12:33:39 1997 @@ -83,6 +83,8 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff -u --recursive --new-file v2.1.43/linux/include/asm-i386/ioctls.h linux/include/asm-i386/ioctls.h --- v2.1.43/linux/include/asm-i386/ioctls.h Wed Jul 17 05:10:03 1996 +++ linux/include/asm-i386/ioctls.h Thu Jun 26 12:33:39 1997 @@ -44,6 +44,9 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ + #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIOCLEX 0x5451 #define FIOASYNC 0x5452 diff -u --recursive --new-file v2.1.43/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v2.1.43/linux/include/asm-i386/unistd.h Thu May 29 21:53:08 1997 +++ linux/include/asm-i386/unistd.h Thu Jun 26 12:33:39 1997 @@ -175,6 +175,8 @@ #define __NR_query_module 167 #define __NR_poll 168 #define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 /* user-visible error numbers are in the range -1 - -122: see */ diff -u --recursive --new-file v2.1.43/linux/include/asm-m68k/ioctls.h linux/include/asm-m68k/ioctls.h --- v2.1.43/linux/include/asm-m68k/ioctls.h Fri Apr 5 03:08:13 1996 +++ linux/include/asm-m68k/ioctls.h Thu Jun 26 12:33:39 1997 @@ -44,6 +44,9 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ + #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIOCLEX 0x5451 #define FIOASYNC 0x5452 diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/addrspace.h linux/include/asm-mips/addrspace.h --- v2.1.43/linux/include/asm-mips/addrspace.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/addrspace.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,52 @@ +/* + * 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) 1996 by Ralf Baechle + * + * Defitions for the address spaces of the MIPS CPUs. + */ +#ifndef __ASM_MIPS_ADDRSPACE_H +#define __ASM_MIPS_ADDRSPACE_H + +/* + * 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) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0)) +#define KSEG1ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1)) +#define KSEG2ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2)) +#define KSEG3ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3)) + +/* + * Memory segments (64bit kernel mode addresses) + */ +#define XKUSEG 0x0000000000000000 +#define XKSSEG 0x4000000000000000 +#define XKPHYS 0x8000000000000000 +#define XKSEG 0xc000000000000000 +#define CKSEG0 0xffffffff80000000 +#define CKSEG1 0xffffffffa0000000 +#define CKSSEG 0xffffffffc0000000 +#define CKSEG3 0xffffffffe0000000 + +#endif /* __ASM_MIPS_ADDRSPACE_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/asm.h linux/include/asm-mips/asm.h --- v2.1.43/linux/include/asm-mips/asm.h Mon Dec 25 20:03:01 1995 +++ linux/include/asm-mips/asm.h Thu Jun 26 12:33:39 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * * Some useful macros for MIPS assembler code * @@ -16,9 +16,7 @@ #ifndef __ASM_ASM_H #define __ASM_ASM_H -#include -#include -#include +#include #ifndef CAT #ifdef __STDC__ @@ -30,32 +28,14 @@ #endif /* - * Macros to handle different pointer sizes for 32/64-bit code + * Macros to handle different pointer/register sizes for 32/64-bit code + * + * 64 bit address space isn't used yet, so we may use the R3000 32 bit + * defines for now. */ -#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 @@ -63,11 +43,11 @@ */ #ifdef __PIC__ #define CPRESTORE(register) \ - .cprestore register + .cprestore register #define CPADD(register) \ - .cpadd register + .cpadd register #define CPLOAD(register) \ - .cpload register + .cpload register #else #define CPRESTORE(register) #define CPADD(register) @@ -78,64 +58,67 @@ * LEAF - declare leaf routine */ #define LEAF(symbol) \ - .globl symbol; \ - .align 2; \ - TYPE(symbol,function); \ - .ent symbol,0; \ -symbol: .frame sp,0,ra + .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 + .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) + .end function; \ + .size function,.-function /* * EXPORT - export definition of symbol */ #define EXPORT(symbol) \ - .globl symbol; \ + .globl symbol; \ symbol: /* * ABS - export absolute symbol */ #define ABS(symbol,value) \ - .globl symbol; \ -symbol = value + .globl symbol; \ +symbol = value #define PANIC(msg) \ - la a0,8f; \ - jal panic; \ - nop; \ -9: b 9b; \ - nop; \ - TEXT(msg) + .set push; \ + .set reorder; \ + la a0,8f; \ + jal panic; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) /* * Print formated string */ #define PRINT(string) \ - la a0,8f; \ - jal printk; \ - nop; \ - TEXT(string) + .set push; \ + .set reorder; \ + la a0,8f; \ + jal printk; \ + .set pop; \ + TEXT(string) #define TEXT(msg) \ - .data; \ -8: .asciiz msg; \ - .text + .data; \ +8: .asciiz msg; \ + .previous; /* * Build text tables @@ -143,68 +126,19 @@ #define TTABLE(string) \ .text; \ .word 1f; \ + .previous; \ .data; \ 1: .asciz string; \ - .text; + .previous /* - * 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. + * MIPS IV pref instruction. * Use with .set noreorder only! + * + * MIPS IV implementations are free to treat this as a nop. The R5000 + * is one of them. So we should have an option not to use this instruction. */ -#if defined (CONFIG_CPU_R8000) || defined(CONFIG_CPU_R10000) +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) #define PREF(hint,addr) \ pref hint,addr #define PREFX(hint,addr) \ @@ -215,34 +149,226 @@ #endif /* - * R8000/R10000 (MIPS ISA IV) movn/movz instructions and - * equivalents for old CPUs. Use with .set noreorder only! + * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. */ -#if defined (CONFIG_CPU_R8000) || defined (CONFIG_CPU_R10000) +#if _MIPS_ISA == _MIPS_ISA_MIPS1 #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 \ + .set push; \ + .set reorder; \ + beqz rt,9f; \ + move rd,rs; \ + .set pop; \ 9: #define MOVZ(rd,rs,rt) \ - beqzl rt,9f \ - movz rd,rt \ + .set push; \ + .set reorder; \ + bnez rt,9f; \ + move rd,rt; \ + .set pop; \ 9: -#else /* R2000, R3000 */ +#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) #define MOVN(rd,rs,rt) \ - beqz rt,9f \ - nop \ - move rd,rs \ + .set push; \ + .set noreorder; \ + bnezl rt,9f; \ + move rd,rs; \ + .set pop; \ 9: #define MOVZ(rd,rs,rt) \ - bneqz rt,9f \ - nop \ - movz rd,rt \ + .set push; \ + .set noreorder; \ + beqzl rt,9f; \ + movz rd,rs; \ + .set pop; \ 9: +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) +#define MOVN(rd,rs,rt) \ + movn rd,rs,rt +#define MOVZ(rd,rs,rt) \ + movz rd,rs,rt +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */ + +/* + * Stack alignment + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) +#define ALSZ 7 +#define ALMASK ~7 +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) +#define ALSZ 15 +#define ALMASK ~15 +#endif + +/* + * Size of a register + */ +#ifdef __mips64 +#define SZREG 8 +#else +#define SZREG 4 +#endif + +/* + * Use the following macros in assemblercode to load/store registers, + * pointers etc. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) +#define REG_S sw +#define REG_L lw +#define PTR_SUBU subu +#define PTR_ADDU addu +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) +#define REG_S sd +#define REG_L ld +/* We still live in a 32 bit address space ... */ +#define PTR_SUBU subu +#define PTR_ADDU addu +#endif + +/* + * How to add/sub/load/store/shift C int variables. + */ +#if (_MIPS_SZINT == 32) +#define INT_ADD add +#define INT_ADDI addi +#define INT_ADDU addu +#define INT_ADDIU addiu +#define INT_SUB add +#define INT_SUBI subi +#define INT_SUBU subu +#define INT_SUBIU subu +#define INT_L lw +#define INT_S sw +#define LONG_SLL sll +#define LONG_SLLV sllv +#define LONG_SRL srl +#define LONG_SRLV srlv +#define LONG_SRA sra +#define LONG_SRAV srav +#endif + +#if (_MIPS_SZINT == 64) +#define INT_ADD dadd +#define INT_ADDI daddi +#define INT_ADDU daddu +#define INT_ADDIU daddiu +#define INT_SUB dadd +#define INT_SUBI dsubi +#define INT_SUBU dsubu +#define INT_SUBIU dsubu +#define INT_L ld +#define INT_S sd +#define LONG_SLL dsll +#define LONG_SLLV dsllv +#define LONG_SRL dsrl +#define LONG_SRLV dsrlv +#define LONG_SRA dsra +#define LONG_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift C long variables. + */ +#if (_MIPS_SZLONG == 32) +#define LONG_ADD add +#define LONG_ADDI addi +#define LONG_ADDU addu +#define LONG_ADDIU addiu +#define LONG_SUB add +#define LONG_SUBI subi +#define LONG_SUBU subu +#define LONG_SUBIU subu +#define LONG_L lw +#define LONG_S sw +#define LONG_SLL sll +#define LONG_SLLV sllv +#define LONG_SRL srl +#define LONG_SRLV srlv +#define LONG_SRA sra +#define LONG_SRAV srav +#endif + +#if (_MIPS_SZLONG == 64) +#define LONG_ADD dadd +#define LONG_ADDI daddi +#define LONG_ADDU daddu +#define LONG_ADDIU daddiu +#define LONG_SUB dadd +#define LONG_SUBI dsubi +#define LONG_SUBU dsubu +#define LONG_SUBIU dsubu +#define LONG_L ld +#define LONG_S sd +#define LONG_SLL dsll +#define LONG_SLLV dsllv +#define LONG_SRL dsrl +#define LONG_SRLV dsrlv +#define LONG_SRA dsra +#define LONG_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift pointers. + */ +#if (_MIPS_SZLONG == 32) +#define PTR_ADD add +#define PTR_ADDI addi +#define PTR_ADDU addu +#define PTR_ADDIU addiu +#define PTR_SUB add +#define PTR_SUBI subi +#define PTR_SUBU subu +#define PTR_SUBIU subu +#define PTR_L lw +#define PTR_S sw +#define PTR_SLL sll +#define PTR_SLLV sllv +#define PTR_SRL srl +#define PTR_SRLV srlv +#define PTR_SRA sra +#define PTR_SRAV srav + +#define PTR_SCALESHIFT 2 +#endif + +#if (_MIPS_SZLONG == 64) +#define PTR_ADD dadd +#define PTR_ADDI daddi +#define PTR_ADDU daddu +#define PTR_ADDIU daddiu +#define PTR_SUB dadd +#define PTR_SUBI dsubi +#define PTR_SUBU dsubu +#define PTR_SUBIU dsubu +#define PTR_L ld +#define PTR_S sd +#define PTR_SLL dsll +#define PTR_SLLV dsllv +#define PTR_SRL dsrl +#define PTR_SRLV dsrlv +#define PTR_SRA dsra +#define PTR_SRAV dsrav + +#define PTR_SCALESHIFT 3 +#endif + +/* + * Some cp0 registers were extended to 64bit for MIPS III. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) +#define MFC0 mfc0 +#define MTC0 mtc0 +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) +#define MFC0 dmfc0 +#define MTC0 dmtc0 #endif #endif /* __ASM_ASM_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h --- v2.1.43/linux/include/asm-mips/asmmacro.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/asmmacro.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,115 @@ +/* $Id: asmmacro.h,v 1.1 1997/06/06 09:38:18 ralf Exp $ + * asmmacro.h: Assembler macros to make things easier to read. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#ifndef __MIPS_ASMMACRO_H +#define __MIPS_ASMMACRO_H + +#include + +#define FPU_SAVE_16ODD(thread) \ + swc1 $f1, (THREAD_FPU + 0x08)(thread); \ + swc1 $f3, (THREAD_FPU + 0x18)(thread); \ + swc1 $f5, (THREAD_FPU + 0x28)(thread); \ + swc1 $f7, (THREAD_FPU + 0x38)(thread); \ + swc1 $f9, (THREAD_FPU + 0x48)(thread); \ + swc1 $f11, (THREAD_FPU + 0x58)(thread); \ + swc1 $f13, (THREAD_FPU + 0x68)(thread); \ + swc1 $f15, (THREAD_FPU + 0x78)(thread); \ + swc1 $f17, (THREAD_FPU + 0x88)(thread); \ + swc1 $f19, (THREAD_FPU + 0x98)(thread); \ + swc1 $f21, (THREAD_FPU + 0xa8)(thread); \ + swc1 $f23, (THREAD_FPU + 0xb8)(thread); \ + swc1 $f25, (THREAD_FPU + 0xc8)(thread); \ + swc1 $f27, (THREAD_FPU + 0xd8)(thread); \ + swc1 $f29, (THREAD_FPU + 0xe8)(thread); \ + swc1 $f31, (THREAD_FPU + 0xf8)(thread); + + +#define FPU_RESTORE_16ODD(thread) \ + lwc1 $f1, (THREAD_FPU + 0x08)(thread); \ + lwc1 $f3, (THREAD_FPU + 0x18)(thread); \ + lwc1 $f5, (THREAD_FPU + 0x28)(thread); \ + lwc1 $f7, (THREAD_FPU + 0x38)(thread); \ + lwc1 $f9, (THREAD_FPU + 0x48)(thread); \ + lwc1 $f11, (THREAD_FPU + 0x58)(thread); \ + lwc1 $f13, (THREAD_FPU + 0x68)(thread); \ + lwc1 $f15, (THREAD_FPU + 0x78)(thread); \ + lwc1 $f17, (THREAD_FPU + 0x88)(thread); \ + lwc1 $f19, (THREAD_FPU + 0x98)(thread); \ + lwc1 $f21, (THREAD_FPU + 0xa8)(thread); \ + lwc1 $f23, (THREAD_FPU + 0xb8)(thread); \ + lwc1 $f25, (THREAD_FPU + 0xc8)(thread); \ + lwc1 $f27, (THREAD_FPU + 0xd8)(thread); \ + lwc1 $f29, (THREAD_FPU + 0xe8)(thread); \ + lwc1 $f31, (THREAD_FPU + 0xf8)(thread); + +#define FPU_SAVE_16EVEN(thread, tmp) \ + cfc1 tmp, fcr31; \ + swc1 $f2, (THREAD_FPU + 0x010)(thread); \ + swc1 $f4, (THREAD_FPU + 0x020)(thread); \ + swc1 $f6, (THREAD_FPU + 0x030)(thread); \ + swc1 $f8, (THREAD_FPU + 0x040)(thread); \ + swc1 $f10, (THREAD_FPU + 0x050)(thread); \ + swc1 $f12, (THREAD_FPU + 0x060)(thread); \ + swc1 $f14, (THREAD_FPU + 0x070)(thread); \ + swc1 $f16, (THREAD_FPU + 0x080)(thread); \ + swc1 $f18, (THREAD_FPU + 0x090)(thread); \ + swc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + swc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + swc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + swc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + swc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + swc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread); + + +#define FPU_RESTORE_16EVEN(thread, tmp) \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ + lwc1 $f2, (THREAD_FPU + 0x010)(thread); \ + lwc1 $f4, (THREAD_FPU + 0x020)(thread); \ + lwc1 $f6, (THREAD_FPU + 0x030)(thread); \ + lwc1 $f8, (THREAD_FPU + 0x040)(thread); \ + lwc1 $f10, (THREAD_FPU + 0x050)(thread); \ + lwc1 $f12, (THREAD_FPU + 0x060)(thread); \ + lwc1 $f14, (THREAD_FPU + 0x070)(thread); \ + lwc1 $f16, (THREAD_FPU + 0x080)(thread); \ + lwc1 $f18, (THREAD_FPU + 0x090)(thread); \ + lwc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + lwc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + lwc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + lwc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + lwc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + lwc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + ctc1 tmp, fcr31; + +#define CPU_SAVE_NONSCRATCH(thread) \ + sw s0, THREAD_REG16(thread); \ + sw s1, THREAD_REG17(thread); \ + sw s2, THREAD_REG18(thread); \ + sw s3, THREAD_REG19(thread); \ + sw s4, THREAD_REG20(thread); \ + sw s5, THREAD_REG21(thread); \ + sw s6, THREAD_REG22(thread); \ + sw s7, THREAD_REG23(thread); \ + sw gp, THREAD_REG28(thread); \ + sw sp, THREAD_REG29(thread); \ + sw fp, THREAD_REG30(thread); + +#define CPU_RESTORE_NONSCRATCH(thread) \ + lw s0, THREAD_REG16(thread); \ + lw s1, THREAD_REG17(thread); \ + lw s2, THREAD_REG18(thread); \ + lw s3, THREAD_REG19(thread); \ + lw s4, THREAD_REG20(thread); \ + lw s5, THREAD_REG21(thread); \ + lw s6, THREAD_REG22(thread); \ + lw s7, THREAD_REG23(thread); \ + lw gp, THREAD_REG28(thread); \ + lw sp, THREAD_REG29(thread); \ + lw fp, THREAD_REG30(thread); \ + lw ra, THREAD_REG31(thread); + +#endif /* !(__MIPS_ASMMACRO_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h --- v2.1.43/linux/include/asm-mips/atomic.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/atomic.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,185 @@ +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + * + * But use these as seldom as possible since they are much more slower + * than regular operations. + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_ATOMIC_H +#define __ASM_MIPS_ATOMIC_H + +#include + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x) + +#ifdef __SMP__ +typedef struct { volatile int counter; } atomic_t; +#else +typedef struct { int counter; } atomic_t; +#endif + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) ((v)->counter = (i)) + +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) + +#include + +/* + * The MIPS I implementation is only atomic with respect to + * interrupts. R3000 based multiprocessor machines are rare anyway ... + */ +extern __inline__ void atomic_add(int i, volatile atomic_t * v) +{ + int flags; + + save_flags(flags); + cli(); + *v += i; + restore_flags(flags); +} + +extern __inline__ void atomic_sub(int i, volatile atomic_t * v) +{ + int flags; + + save_flags(flags); + cli(); + *v -= i; + restore_flags(flags); +} + +extern __inline__ int atomic_add_return(int i, atomic_t * v) +{ + int temp, flags; + + save_flags(flags); + cli(); + temp = *v; + temp += i; + *v = temp; + restore_flags(flags); + + return temp; +} + +extern __inline__ int atomic_sub_return(int i, atomic_t * v) +{ + int temp, flags; + + save_flags(flags); + cli(); + temp = *v; + temp -= i; + *v = temp; + restore_flags(flags); + + return temp; +} +#endif + +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) +/* + * ... while for MIPS II and better we can use ll/sc instruction. This + * implementation is SMP safe ... + */ +extern __inline__ void atomic_add(int i, volatile atomic_t * v) +{ + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0,%1\n\t" + "addu\t%0,%2\n\t" + "sc\t%0,%1\n\t" + "beqz\t%0,1b" + :"=&r" (temp), + "=m" (__atomic_fool_gcc(v)) + :"Ir" (i), + "m" (__atomic_fool_gcc(v))); +} + +extern __inline__ void atomic_sub(int i, volatile atomic_t * v) +{ + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0,%1\n\t" + "subu\t%0,%2\n\t" + "sc\t%0,%1\n\t" + "beqz\t%0,1b" + :"=&r" (temp), + "=m" (__atomic_fool_gcc(v)) + :"Ir" (i), + "m" (__atomic_fool_gcc(v))); +} + +/* + * Same as above, but return the result value + */ +extern __inline__ int atomic_add_return(int i, atomic_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + ".set\tnoreorder\n" + "1:\tll\t%1,%2\n\t" + "addu\t%0,%1,%3\n\t" + "sc\t%0,%2\n\t" + "beqz\t%0,1b\n\t" + "addu\t%0,%1,%3\n\t" + ".set\treorder" + :"=&r" (result), + "=&r" (temp), + "=m" (__atomic_fool_gcc(v)) + :"Ir" (i), + "m" (__atomic_fool_gcc(v))); + + return result; +} + +extern __inline__ int atomic_sub_return(int i, atomic_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + ".set\tnoreorder\n" + "1:\tll\t%1,%2\n\t" + "subu\t%0,%1,%3\n\t" + "sc\t%0,%2\n\t" + "beqz\t%0,1b\n\t" + "subu\t%0,%1,%3\n\t" + ".set\treorder" + :"=&r" (result), + "=&r" (temp), + "=m" (__atomic_fool_gcc(v)) + :"Ir" (i), + "m" (__atomic_fool_gcc(v))); + + return result; +} +#endif + +#define atomic_dec_return(v) atomic_sub_return(1,(v)) +#define atomic_inc_return(v) atomic_add_return(1,(v)) + +#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +#define atomic_inc(v) atomic_add(1,(v)) +#define atomic_dec(v) atomic_sub(1,(v)) + +#endif /* __ASM_MIPS_ATOMIC_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v2.1.43/linux/include/asm-mips/bitops.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/bitops.h Thu Jun 26 12:33:39 1997 @@ -5,15 +5,55 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1994, 1995 Ralf Baechle + * Copyright (c) 1994, 1995, 1996 Ralf Baechle */ #ifndef __ASM_MIPS_BITOPS_H #define __ASM_MIPS_BITOPS_H -#if __mips > 1 +#ifdef __KERNEL__ + +#include +#include + +/* + * Only disable interrupt for kernel mode stuff to keep usermode stuff + * that dares to use kernel include files alive. + */ +#define __bi_flags unsigned long flags +#define __bi_cli() __cli() +#define __bi_save_flags(x) __save_flags(x) +#define __bi_restore_flags(x) __restore_flags(x) +#else +#define __bi_flags +#define __bi_cli() +#define __bi_save_flags(x) +#define __bi_restore_flags(x) +#endif /* __KERNEL__ */ + +/* + * Note that the bit operations are defined on arrays of 32 bit sized + * elements. With respect to a future 64 bit implementation it is + * wrong to use long *. Use u32 * or int *. + */ +extern __inline__ void set_bit(int nr, void *addr); +extern __inline__ void clear_bit(int nr, void *addr); +extern __inline__ void change_bit(int nr, void *addr); +extern __inline__ int test_and_set_bit(int nr, void *addr); +extern __inline__ int test_and_clear_bit(int nr, void *addr); +extern __inline__ int test_and_change_bit(int nr, void *addr); + +extern __inline__ int test_bit(int nr, const void *addr); +#ifndef __MIPSEB__ +extern __inline__ int find_first_zero_bit (void *addr, unsigned size); +#endif +extern __inline__ int find_next_zero_bit (void * addr, int size, int offset); +extern __inline__ unsigned long ffz(unsigned long word); + +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) /* - * These functions for MIPS ISA >= 2 are interrupt and SMP proof and + * These functions for MIPS ISA > 1 are interrupt and SMP proof and * interrupt friendly */ #include @@ -21,7 +61,42 @@ /* * The following functions will only work for the R4000! */ -extern __inline__ int set_bit(int nr, void *addr) + +extern __inline__ void set_bit(int nr, void *addr) +{ + int mask, mw; + + addr += ((nr >> 3) & ~3); + mask = 1 << (nr & 0x1f); + do { + mw = load_linked(addr); + } while (!store_conditional(addr, mw|mask)); +} + +extern __inline__ void clear_bit(int nr, void *addr) +{ + int mask, mw; + + addr += ((nr >> 3) & ~3); + mask = 1 << (nr & 0x1f); + do { + mw = load_linked(addr); + } + while (!store_conditional(addr, mw & ~mask)); +} + +extern __inline__ void change_bit(int nr, void *addr) +{ + int mask, mw; + + addr += ((nr >> 3) & ~3); + mask = 1 << (nr & 0x1f); + do { + mw = load_linked(addr); + } while (!store_conditional(addr, mw ^ mask)); +} + +extern __inline__ int test_and_set_bit(int nr, void *addr) { int mask, retval, mw; @@ -30,13 +105,12 @@ do { mw = load_linked(addr); retval = (mask & mw) != 0; - } - while (!store_conditional(addr, mw|mask)); + } while (!store_conditional(addr, mw|mask)); return retval; } -extern __inline__ int clear_bit(int nr, void *addr) +extern __inline__ int test_and_clear_bit(int nr, void *addr) { int mask, retval, mw; @@ -51,7 +125,7 @@ return retval; } -extern __inline__ int change_bit(int nr, void *addr) +extern __inline__ int test_and_change_bit(int nr, void *addr) { int mask, retval, mw; @@ -60,124 +134,165 @@ do { mw = load_linked(addr); retval = (mask & mw) != 0; - } - while (!store_conditional(addr, mw ^ mask)); + } while (!store_conditional(addr, mw ^ mask)); return retval; } -#else /* __mips <= 1 */ +#else /* MIPS I */ -/* - * 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 +extern __inline__ void set_bit(int nr, void * addr) +{ + int mask; + int *a = addr; + __bi_flags; -#ifdef __KERNEL__ -/* - * 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() -#define __save_flags(x) save_flags(x) -#define __restore_flags(x) restore_flags(x) -#endif /* __KERNEL__ */ + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_flags(flags); + __bi_cli(); + *a |= mask; + __bi_restore_flags(flags); +} -extern __inline__ int set_bit(int nr, void * addr) +extern __inline__ void clear_bit(int nr, void * addr) +{ + int mask; + int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_flags(flags); + __bi_cli(); + *a &= ~mask; + __bi_restore_flags(flags); +} + +extern __inline__ void change_bit(int nr, void * addr) +{ + int mask; + int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_flags(flags); + __bi_cli(); + *a ^= mask; + __bi_restore_flags(flags); +} + +extern __inline__ int test_and_set_bit(int nr, void * addr) { int mask, retval; int *a = addr; - __flags; + __bi_flags; a += nr >> 5; mask = 1 << (nr & 0x1f); - __save_flags(flags); - __cli(); + __bi_save_flags(flags); + __bi_cli(); retval = (mask & *a) != 0; *a |= mask; - __restore_flags(flags); + __bi_restore_flags(flags); return retval; } -extern __inline__ int clear_bit(int nr, void * addr) +extern __inline__ int test_and_clear_bit(int nr, void * addr) { int mask, retval; int *a = addr; - __flags; + __bi_flags; a += nr >> 5; mask = 1 << (nr & 0x1f); - __save_flags(flags); - __cli(); + __bi_save_flags(flags); + __bi_cli(); retval = (mask & *a) != 0; *a &= ~mask; - __restore_flags(flags); + __bi_restore_flags(flags); return retval; } -extern __inline__ int change_bit(int nr, void * addr) +extern __inline__ int test_and_change_bit(int nr, void * addr) { int mask, retval; int *a = addr; - __flags; + __bi_flags; a += nr >> 5; mask = 1 << (nr & 0x1f); - __save_flags(flags); - __cli(); + __bi_save_flags(flags); + __bi_cli(); retval = (mask & *a) != 0; *a ^= mask; - __restore_flags(flags); + __bi_restore_flags(flags); return retval; } -#undef __flags -#undef __cli() -#undef __save_flags(x) -#undef __restore_flags(x) +#undef __bi_flags +#undef __bi_cli() +#undef __bi_save_flags(x) +#undef __bi_restore_flags(x) -#endif /* __mips <= 1 */ +#endif /* MIPS I */ extern __inline__ int test_bit(int nr, const void *addr) { - return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31)); + return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0; } +#ifndef __MIPSEB__ + +/* Little endian versions. */ + extern __inline__ int find_first_zero_bit (void *addr, unsigned size) { + unsigned long dummy; int res; if (!size) return 0; - __asm__(".set\tnoreorder\n\t" + __asm__ (".set\tnoreorder\n\t" ".set\tnoat\n" - "1:\tsubu\t$1,%2,%0\n\t" + "1:\tsubu\t$1,%6,%0\n\t" "blez\t$1,2f\n\t" - "lw\t$1,(%4)\n\t" - "addiu\t%4,%4,4\n\t" + "lw\t$1,(%5)\n\t" + "addiu\t%5,4\n\t" +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) "beql\t%1,$1,1b\n\t" - "addiu\t%0,%0,32\n\t" + "addiu\t%0,32\n\t" +#else + "addiu\t%0,32\n\t" + "beq\t%1,$1,1b\n\t" + "nop\n\t" + "subu\t%0,32\n\t" +#endif +#ifdef __MIPSEB__ +#error "Fix this for big endian" +#endif /* __MIPSEB__ */ "li\t%1,1\n" - "1:\tand\t%4,$1,%1\n\t" - "beq\t$0,%4,2f\n\t" + "1:\tand\t%2,$1,%1\n\t" + "beqz\t%2,2f\n\t" "sll\t%1,%1,1\n\t" - "bne\t$0,%1,1b\n\t" + "bnez\t%1,1b\n\t" "add\t%0,%0,1\n\t" ".set\tat\n\t" ".set\treorder\n" "2:" - : "=r" (res) - : "r" ((unsigned int) 0xffffffff), - "r" (size), - "0" ((signed int) 0), - "r" (addr) + : "=r" (res), + "=r" (dummy), + "=r" (addr) + : "0" ((signed int) 0), + "1" ((unsigned int) 0xffffffff), + "2" (addr), + "r" (size) : "$1"); return res; @@ -185,26 +300,32 @@ extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) { - unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + unsigned int *p = ((unsigned int *) addr) + (offset >> 5); int set = 0, bit = offset & 31, res; + unsigned long dummy; if (bit) { /* * Look for zero in first byte */ +#ifdef __MIPSEB__ +#error "Fix this for big endian byte order" +#endif __asm__(".set\tnoreorder\n\t" ".set\tnoat\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" - "addiu\t%0,%0,1\n\t" + "1:\tand\t$1,%4,%1\n\t" + "beqz\t$1,1f\n\t" + "sll\t%1,%1,1\n\t" + "bnez\t%1,1b\n\t" + "addiu\t%0,1\n\t" ".set\tat\n\t" ".set\treorder\n" - : "=r" (set) - : "r" (*p >> bit), - "r" (1), - "0" (0) + "1:" + : "=r" (set), + "=r" (dummy) + : "0" (0), + "1" (1 << bit), + "r" (*p) : "$1"); if (set < (32 - bit)) return set + offset; @@ -214,10 +335,12 @@ /* * No zero yet, search remaining full bytes for a zero */ - res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); - return (offset + set + res); + res = find_first_zero_bit(p, size - 32 * (p - (unsigned int *) addr)); + return offset + set + res; } +#endif /* !(__MIPSEB__) */ + /* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. @@ -227,7 +350,7 @@ unsigned int __res; unsigned int mask = 1; - __asm__ __volatile__ ( + __asm__ ( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "move\t%0,$0\n" @@ -239,11 +362,183 @@ ".set\tat\n\t" ".set\treorder\n" "2:\n\t" - : "=r" (__res), "=r" (mask) + : "=&r" (__res), "=r" (mask) : "r" (word), "1" (mask) : "$1"); return __res; } + +#ifdef __MIPSEB__ +/* For now I steal the Sparc C versions, no need for speed, just need to + * get it working. + */ +/* find_next_zero_bit() finds the first zero bit in a bit string of length + * 'size' bits, starting the search at bit 'offset'. This is largely based + * on Linus's ALPHA routines, which are pretty portable BTW. + */ + +extern __inline__ int find_next_zero_bit(void *addr, int size, int offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) + goto found_first; + if (~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while (size & ~31UL) { + if (~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; +found_middle: + return result + ffz(tmp); +} + +/* Linus sez that gcc can optimize the following correctly, we'll see if this + * holds on the Sparc as it does for the ALPHA. + */ + +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + +#endif /* (__MIPSEB__) */ + +/* Now for the ext2 filesystem bit operations and helper routines. */ + +#ifdef __MIPSEB__ +extern __inline__ int ext2_set_bit(int nr,void * addr) +{ + int mask, retval, flags; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + save_flags(flags); cli(); + retval = (mask & *ADDR) != 0; + *ADDR |= mask; + restore_flags(flags); + return retval; +} + +extern __inline__ int ext2_clear_bit(int nr, void * addr) +{ + int mask, retval, flags; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + save_flags(flags); cli(); + retval = (mask & *ADDR) != 0; + *ADDR &= ~mask; + restore_flags(flags); + return retval; +} + +extern __inline__ int ext2_test_bit(int nr, const void * addr) +{ + int mask; + const unsigned char *ADDR = (const unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return ((mask & *ADDR) != 0); +} + +#define ext2_find_first_zero_bit(addr, size) \ + ext2_find_next_zero_bit((addr), (size), 0) + +static __inline__ unsigned long __swab32(unsigned long val) +{ + return ((val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24)); +} + +extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if(offset) { + /* We hold the little endian value in tmp, but then the + * shift is illegal. So we could keep a big endian value + * in tmp, like this: + * + * tmp = __swab32(*(p++)); + * tmp |= ~0UL >> (32-offset); + * + * but this would decrease preformance, so we change the + * shift: + */ + tmp = *(p++); + tmp |= __swab32(~0UL >> (32-offset)); + if(size < 32) + goto found_first; + if(~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while(size & ~31UL) { + if(~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if(!size) + return result; + tmp = *p; + +found_first: + /* tmp is little endian, so we would have to swab the shift, + * see above. But then we have to swab tmp below for ffz, so + * we might as well do this here. + */ + return result + ffz(__swab32(tmp) | (~0UL << size)); +found_middle: + return result + ffz(__swab32(tmp)); +} +#else /* !(__MIPSEB__) */ + +/* Native ext2 byte ordering, just collapse using defines. */ +#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr)) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr)) +#define ext2_test_bit(nr, addr) test_bit((nr), (addr)) +#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size)) +#define ext2_find_next_zero_bit(addr, size, offset) \ + find_next_zero_bit((addr), (size), (offset)) + +/* + * Bitmap functions for the minix filesystem. + * FIXME: These assume that Minix uses the native byte/bitorder. + */ +#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) +#endif /* __KERNEL__ */ #endif /* __ASM_MIPS_BITOPS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h --- v2.1.43/linux/include/asm-mips/bootinfo.h Sat May 24 09:10:25 1997 +++ linux/include/asm-mips/bootinfo.h Thu Jun 26 12:33:39 1997 @@ -1,11 +1,8 @@ /* * bootinfo.h -- Definition of the Linux/MIPS boot information structure * - * Copyright (C) 1994 by Waldorf Electronics - * Written by Ralf Baechle and Andreas Busse - * - * Based on Linux/68k linux/include/linux/bootstrap.h - * Copyright (C) 1992 by Greg Harp + * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse, + * Stoned Elipot and Paul M. Antoine. * * 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 @@ -14,19 +11,95 @@ #ifndef __ASM_MIPS_BOOTINFO_H #define __ASM_MIPS_BOOTINFO_H +/* XXX */ +#include + +#if 0 /* * Valid machtype values + * FIXME: note that we really need a hierarchy for this stuff, as there are + * several models of DECStation (for example). PMA + */ +#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 4 /* almost a clone ... */ +#define MACH_DECSTATION 5 /* DECStation 5000/2x for now */ +#define MACH_SNI_RM200_PCI 6 /* RM200/RM300/RM400 PCI series */ +#define MACH_SGI_INDY 7 /* R4?K and R5K Indy workstaions */ +#define MACH_LAST 7 + +#define MACH_NAMES {"unknown", "Deskstation rPC44", "Deskstation Tyne", \ + "Acer PICA 61", "Mips Magnum 4000", "DECStation", "RM200 PCI", \ + "SGI INDY" } +#endif + +/* + * Values for machgroup + */ +#define MACH_GROUP_UNKNOWN 0 /* whatever... */ +#define MACH_GROUP_JAZZ 1 /* Jazz */ +#define MACH_GROUP_DEC 2 /* Digital Equipment */ +#define MACH_GROUP_ARC 3 /* Wreckstation Tyne, rPC44, possibly other */ +#define MACH_GROUP_SNI_RM 4 /* Siemens Nixdorf RM series */ +#define MACH_GROUP_ACN 5 +#define MACH_GROUP_SGI 6 /* Silicon Graphics workstations and servers */ + +#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", "SNI", "ACN" } + +/* + * Valid machtype values for group unknown (low order halfword of mips_machtype) + */ +#define MACH_UNKNOWN 0 /* whatever... */ + +#define GROUP_UNKNOWN_NAMES { "unknown" } + +/* + * Valid machtype values for group JAZZ + */ +#define MACH_ACER_PICA_61 0 /* Acer PICA-61 (PICA1) */ +#define MACH_MIPS_MAGNUM_4000 1 /* Mips Magnum 4000 "RC4030" */ +#define MACH_OLIVETTI_M700 2 /* Olivetti M700-10 (-15 ??) */ + +#define GROUP_JAZZ_NAMES { "Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" } + +/* + * Valid machtype for group DEC + */ +/* FIXME: this is a very fuzzy name, and we got a big "name space now" */ +/* So otiginal DEC codes can be used -Stoned */ +#define MACH_DECSTATION 0 /* DECStation 5000/2x for now */ + +#define GROUP_DEC_NAMES { "3min" } + +/* + * Valid machtype for group ARC */ -#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_DESKSTATION_RPC44 0 /* Deskstation rPC44 */ +#define MACH_DESKSTATION_TYNE 1 /* Deskstation Tyne */ -#define MACH_NAMES { "unknown", "Deskstation rPC44", "Deskstation Tyne", \ - "Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" } +#define GROUP_ARC_NAMES { "Deskstation rPC44", "Deskstation Tyne" } + +/* + * Valid machtype for group SNI_RM + */ +#define MACH_SNI_RM200_PCI 0 /* RM200/RM300/RM400 PCI series */ + +#define GROUP_SNI_RM_NAMES { "RM200 PCI" } + +/* + * Valid machtype for group ACN + */ +#define MACH_ACN_MIPS_BOARD 0 /* ACN MIPS single board */ + +#define GROUP_ACN_NAMES { "ACN" } + +/* + * Valid machtype for group SGI + */ +#define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstaions */ /* * Valid cputype values @@ -52,200 +125,191 @@ #define CPU_R6000A 18 #define CPU_R8000 19 #define CPU_R10000 20 -#define CPU_LAST 20 +#define CPU_R4300 21 +#define CPU_R4650 22 +#define CPU_R4700 23 +#define CPU_R5000 24 +#define CPU_R5000A 25 +#define CPU_R4640 26 +#define CPU_LAST 27 #define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \ "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC", \ "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000", \ - "R6000A", "R8000", "R10000" } + "R6000A", "R8000", "R10000", "R4300", "R4650", "R4700", "R5000", \ + "R5000A", "R4640" } #define CL_SIZE (80) #ifndef __LANGUAGE_ASSEMBLY__ /* - * Some machine parameters passed by MILO. Note that bootinfo - * *must* be in the data segment since the kernel clears the - * bss segment directly after startup. + * Some machine parameters passed by the bootloaders. */ struct drive_info_struct { char dummy[32]; - }; - -struct bootinfo { - /* - * machine type - */ - unsigned long machtype; - - /* - * system CPU & FPU - */ - unsigned long cputype; - - /* - * Installed RAM - */ - unsigned long memlower; - unsigned long memupper; - - /* - * Cache Sizes (0xffffffff = unknown) - */ - unsigned long icache_size; - unsigned long icache_linesize; - unsigned long dcache_size; - unsigned long dcache_linesize; - unsigned long scache_size; - unsigned long scache_linesize; - - /* - * TLB Info - */ - unsigned long tlb_entries; - - /* - * DMA buffer size (Deskstation only) - */ - unsigned long dma_cache_size; - unsigned long dma_cache_base; - - /* - * Ramdisk Info - */ - unsigned long ramdisk_flags; /* ramdisk flags */ - unsigned long ramdisk_base; /* address of the ram disk in mem */ - - /* - * Boot flags for the kernel - */ - unsigned long mount_root_rdonly; - struct drive_info_struct drive_info; - - /* - * Video ram info (not in tty.h) - */ - unsigned long vram_base; /* video ram base address */ - - char command_line[CL_SIZE]; /* kernel command line parameters */ - }; -#if 0 +/* This is the same as in Milo but renamed for the sake of kernel's */ +/* namespace */ +typedef struct mips_arc_DisplayInfo { /* video adapter information */ + unsigned short cursor_x; + unsigned short cursor_y; + unsigned short columns; + unsigned short lines; +} mips_arc_DisplayInfo; + /* * 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, +enum bi_tag { + /* + * not a real tag + */ + tag_dummy, + + /* + * machine type + */ + tag_machtype, + + /* + * system CPU & FPU + */ + tag_cputype, + + /* + * Installed RAM + */ + tag_memlower, + tag_memupper, + + /* + * Cache Sizes (0xffffffff = unknown) + */ + tag_icache_size, + tag_icache_linesize, + tag_dcache_size, + tag_dcache_linesize, + tag_scache_size, + tag_scache_linesize, + + /* + * TLB Info + */ + tag_tlb_entries, + + /* + * DMA buffer size (Deskstation only) + */ + tag_dma_cache_size, + tag_dma_cache_base, + + /* + * Ramdisk Info + */ + tag_ramdisk_size, /* ramdisk size in 1024 byte blocks */ + tag_ramdisk_base, /* address of the ram disk in mem */ + + /* + * Boot flags for the kernel + */ + tag_mount_root_rdonly, + tag_drive_info, + + /* + * Video ram info (not in tty.h) + */ + tag_vram_base, /* video ram base address */ + + tag_command_line, /* kernel command line parameters */ + + /* + * machine group + */ + tag_machgroup, /* - * machine type + * info on the display from the ARC BIOS */ - machtype, + tag_arcdisplayinfo, /* - * system CPU & FPU + * tag to pass a complete struct screen_info */ - cputype, + tag_screen_info +}; - /* - * Installed RAM - */ - memlower, - memupper, +/* struct defining a tag */ +typedef struct { + enum bi_tag tag; + unsigned long size; +} tag; - /* - * Cache Sizes (0xffffffff = unknown) - */ - icache_size, - icache_linesize, - dcache_size, - dcache_linesize, - scache_size, - scache_linesize, +/* struct to define a tag and it's data */ +typedef struct { + tag t; + void* d; +} tag_def; + +/* macros for parsing tag list */ +#define TAGVALPTR(t) ((void*)(((void*)(t)) - ((t)->size))) +#define NEXTTAGPTR(t) ((void*)(TAGVALPTR(t) - (sizeof(tag)))) + +/* size macros for tag size field */ +#define UCHARSIZE (sizeof(unsigned char)) +#define ULONGSIZE (sizeof(unsigned long)) +#define UINTSIZE (sizeof(unsigned int)) +#define DRVINFOSIZE (sizeof(struct drive_info_struct)) +#define CMDLINESIZE (sizeof(char[CL_SIZE]) - /* - * TLB Info - */ - tlb_entries, +/* + * For tag readers aka the kernel + */ +tag *bi_TagFind(enum bi_tag type); +void bi_EarlySnarf(void); - /* - * DMA buffer size (Deskstation only) - */ - dma_cache_size, - dma_cache_base, +/* For tag creators aka bootloaders */ +/* Now implemented in Milo 0.26 */ +int bi_TagAdd(enum bi_tag type, unsigned long size, void *data); +int bi_TagAddList(tag_def* taglist); +void bi_TagWalk(void); - /* - * 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, +#ifdef CONFIG_SGI - /* - * Video ram info (not in tty.h) - */ - vram_base, /* video ram base address */ - - command_line /* kernel command line parameters */ - -}; +/* screen info will dissapear... soon */ +#define DEFAULT_SCREEN_INFO {0, 0, {0, 0, }, 0, 0, 158, 0, 0, 0, 62, 0, 16} +#define DEFAULT_DRIVE_INFO { {0,}} + +#else + +/* default values for screen_info variable */ +#define DEFAULT_SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50} +/* default values for drive info */ +#define DEFAULT_DRIVE_INFO { {0,}} -typedef struct { - bi_tag tag; - unsigned long size; -} tag; #endif -extern struct bootinfo boot_info; /* - * Defaults, may be overwritten by milo. We initialize - * them to make sure that both boot_info and screen_info - * are in the .data segment since the .bss segment is - * cleared during startup. - */ -#define BOOT_INFO { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, {{0,}}, 0, "" } -#define SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50} - -#else /* !__LANGUAGE_ASSEMBLY__ */ - -/* - * Same structure, but as offsets for usage within assembler source. - * Don't mess with struct bootinfo without changing offsets too! - */ - -#define OFFSET_BOOTINFO_MACHTYPE 0 -#define OFFSET_BOOTINFO_CPUTYPE 4 -#define OFFSET_BOOTINFO_MEMLOWER 8 -#define OFFSET_BOOTINFO_MEMUPPER 12 -#define OFFSET_BOOTINFO_ICACHE_SIZE 16 -#define OFFSET_BOOTINFO_ICACHE_LINESIZE 20 -#define OFFSET_BOOTINFO_DCACHE_SIZE 24 -#define OFFSET_BOOTINFO_DCACHE_LINESIZE 28 -#define OFFSET_BOOTINFO_SCACHE_SIZE 32 -#define OFFSET_BOOTINFO_SCACHE_LINESIZE 36 -#define OFFSET_BOOTINFO_TLB_ENTRIES 40 -#define OFFSET_BOOTINFO_DMA_CACHE_SIZE 44 -#define OFFSET_BOOTINFO_DMA_CACHE_BASE 48 -#define OFFSET_BOOTINFO_RAMDISK_SIZE 52 -#define OFFSET_BOOTINFO_RAMDISK_BASE 56 -#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 + * These are the kernel variables initialized from + * the tag. And they have to be initialized to dummy/default + * values in setup.c (or whereever suitable) so they are in + * .data section + */ +extern unsigned long mips_memory_upper; +extern unsigned long mips_cputype; +extern unsigned long mips_machtype; +extern unsigned long mips_machgroup; +extern unsigned long mips_tlb_entries; +extern unsigned long mips_vram_base; +extern unsigned long mips_dma_cache_size; +extern unsigned long mips_dma_cache_base; #endif /* __LANGUAGE_ASSEMBLY__ */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/branch.h linux/include/asm-mips/branch.h --- v2.1.43/linux/include/asm-mips/branch.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/branch.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,26 @@ +/* + * Branch and jump emulation. + * + * 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) 1996, 1997 by Ralf Baechle + */ +#include + +extern inline int delay_slot(struct pt_regs *regs) +{ + return regs->cp0_cause & CAUSEF_BD; +} + +extern int __compute_return_epc(struct pt_regs *regs); +extern inline int compute_return_epc(struct pt_regs *regs) +{ + if (delay_slot(regs)) { + return __compute_return_epc(regs); + } + + regs->cp0_epc += 4; + return 0; +} diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h --- v2.1.43/linux/include/asm-mips/bugs.h Sun Jan 15 14:54:27 1995 +++ linux/include/asm-mips/bugs.h Thu Jun 26 12:33:39 1997 @@ -13,14 +13,15 @@ * void check_bugs(void); */ -extern struct bootinfo boot_info; static void check_wait(void) { printk("Checking for 'wait' instruction... "); - switch(boot_info.cputype) { + switch(mips_cputype) { case CPU_R4200: + case CPU_R4300: case CPU_R4600: + case CPU_R5000: wait_available = 1; printk(" available.\n"); break; diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h --- v2.1.43/linux/include/asm-mips/byteorder.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/byteorder.h Thu Jun 26 12:33:39 1997 @@ -1,91 +1,117 @@ +/* + * Functions depending of the byteorder. + * + * 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, 1996, 1997 by Ralf Baechle + */ #ifndef __ASM_MIPS_BYTEORDER_H #define __ASM_MIPS_BYTEORDER_H +extern unsigned long int ntohl(unsigned long int __x); +extern unsigned short int ntohs(unsigned short int __x); +extern unsigned short int htons(unsigned short int __x); +extern unsigned long int htonl(unsigned long int __x); + +#define __swap32(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))) +#define __swap16(x) \ + ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ + (((unsigned short int)(x) & 0xff00) >> 8))) + +#if defined (__MIPSEB__) + +#ifndef __BIG_ENDIAN +#define __BIG_ENDIAN +#endif + +#ifndef __BIG_ENDIAN_BITFIELD +#define __BIG_ENDIAN_BITFIELD +#endif + +#define __constant_ntohl(x) (x) +#define __constant_ntohs(x) (x) +#define __constant_htonl(x) (x) +#define __constant_htons(x) (x) + +#ifdef __KERNEL__ + /* - * FIXME: Add big endian support + * In-kernel byte order macros to handle stuff like + * byte-order-dependent filesystems etc. */ -#undef ntohl -#undef ntohs -#undef htonl -#undef htons +#define cpu_to_le32(x) __swap32((x)) +#define le32_to_cpu(x) __swap32((x)) +#define cpu_to_le16(x) __swap16((x)) +#define le16_to_cpu(x) __swap16((x)) + +#define cpu_to_be32(x) (x) +#define be32_to_cpu(x) (x) +#define cpu_to_be16(x) (x) +#define be16_to_cpu(x) (x) + +#endif /* __KERNEL__ */ -#if defined (__MIPSEL__) +#elif defined (__MIPSEL__) + +#ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN +#endif + +#ifndef __LITTLE_ENDIAN_BITFIELD #define __LITTLE_ENDIAN_BITFIELD -#elif defined (__MIPSEB__) -#define __BIG_ENDIAN -#define __BIG_ENDIAN_BITFIELD -#else -#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" #endif -extern unsigned long int ntohl(unsigned long int); -extern unsigned short int ntohs(unsigned short int); -extern unsigned long int htonl(unsigned long int); -extern unsigned short int htons(unsigned short int); - -extern __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); +#define __constant_ntohl(x) __swap32(x) +#define __constant_ntohs(x) __swap16(x) +#define __constant_htonl(x) __swap32(x) +#define __constant_htons(x) __swap16(x) + +#ifdef __KERNEL__ /* - * 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). Oh, and the - * big endian routines that are still missing will be fairly - * easy to write :-) + * In-kernel byte order macros to handle stuff like + * byte-order-dependent filesystems etc. */ +#define cpu_to_le32(x) (x) +#define le32_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#define le16_to_cpu(x) (x) + +#define cpu_to_be32(x) __swap32((x)) +#define be32_to_cpu(x) __swap32((x)) +#define cpu_to_be16(x) __swap16((x)) +#define be16_to_cpu(x) __swap16((x)) + +#endif /* __KERNEL__ */ + +#else +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" +#endif -extern __inline__ unsigned long int -__ntohl(unsigned long int x) +extern __inline__ unsigned long int ntohl(unsigned long int __x) { - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); + return __constant_ntohl(__x); } -#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) +extern __inline__ unsigned short int ntohs(unsigned short int __x) { - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); + return __constant_ntohs(__x); } -#define __constant_ntohs(x) \ - ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ - (((unsigned short int)(x) & 0xff00) >> 8))) \ +extern __inline__ unsigned long int htonl(unsigned long int __x) +{ + return __constant_htonl(__x); +} -#define __htonl(x) __ntohl(x) -#define __htons(x) __ntohs(x) -#define __constant_htonl(x) __constant_ntohl(x) -#define __constant_htons(x) __constant_ntohs(x) - -#ifdef __OPTIMIZE__ -# define ntohl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_ntohl((x)) : \ - __ntohl((x))) -# define ntohs(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_ntohs((x)) : \ - __ntohs((x))) -# define htonl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_htonl((x)) : \ - __htonl((x))) -# define htons(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_htons((x)) : \ - __htons((x))) -#endif +extern __inline__ unsigned short int htons(unsigned short int __x) +{ + return __constant_htons(__x); +} #endif /* __ASM_MIPS_BYTEORDER_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cache.h linux/include/asm-mips/cache.h --- v2.1.43/linux/include/asm-mips/cache.h Sun Jan 26 02:07:46 1997 +++ linux/include/asm-mips/cache.h Thu Jun 26 12:33:39 1997 @@ -1,12 +1,12 @@ /* * include/asm-mips/cache.h */ -#ifndef __ARCH_MIPS_CACHE_H -#define __ARCH_MIPS_CACHE_H +#ifndef __ASM_MIPS_CACHE_H +#define __ASM_MIPS_CACHE_H /* bytes per L1 cache line */ #define L1_CACHE_BYTES 32 /* a guess */ #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) -#endif +#endif /* __ASM_MIPS_CACHE_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cachectl.h linux/include/asm-mips/cachectl.h --- v2.1.43/linux/include/asm-mips/cachectl.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/cachectl.h Thu Jun 26 12:33:39 1997 @@ -1,37 +1,24 @@ /* - * include/asm-mips/cachectl.h + * cachectl.h -- defines for MIPS cache control system calls * - * Written by Ralf Baechle, - * Copyright (C) 1994 by Waldorf GMBH + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle */ #ifndef __ASM_MIPS_CACHECTL #define __ASM_MIPS_CACHECTL /* - * cachectl.h -- defines for MIPS cache control system calls - */ - -/* * Options for cacheflush system call */ #define ICACHE (1<<0) /* flush instruction cache */ #define DCACHE (1<<1) /* writeback and flush data cache */ #define BCACHE (ICACHE|DCACHE) /* flush both caches */ -#ifdef __KERNEL__ -#define CACHELINES 512 /* number of cachelines (kludgy) */ - /* - * Cache Operations - for use by assembler code + * Caching modes for the cachectl(2) call + * + * cachctl(2) is currently not supported and returns ENOSYS. */ -#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); +#define CACHEABLE 0 /* make pages cacheable */ +#define UNCACHEABLE 1 /* make pages uncacheable */ -#endif /* !__LANGUAGE_ASSEMBLY__ */ -#endif /* __KERNEL__ */ #endif /* __ASM_MIPS_CACHECTL */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cacheops.h linux/include/asm-mips/cacheops.h --- v2.1.43/linux/include/asm-mips/cacheops.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/cacheops.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,47 @@ +/* + * Cache operations for the cache instruction. + * + * 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. + * + * (C) Copyright 1996, 1997 by Ralf Baechle + */ +#ifndef __ASM_MIPS_CACHEOPS_H +#define __ASM_MIPS_CACHEOPS_H + +/* + * Cache Operations + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_D 0x0d +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_I 0x10 +#define Hit_Invalidate_D 0x11 +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Fill 0x14 +#define Hit_Writeback_Inv_D 0x15 + /* 0x16 is unused */ +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 + /* 0x1a is unused */ +#define Hit_Writeback_SD 0x1b + /* 0x1c is unused */ + /* 0x1e is unused */ +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +#endif /* __ASM_MIPS_CACHEOPS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h --- v2.1.43/linux/include/asm-mips/checksum.h Sun Nov 3 01:04:41 1996 +++ linux/include/asm-mips/checksum.h Thu Jun 26 12:33:39 1997 @@ -31,15 +31,47 @@ * 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); +unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum); /* - * the same as csum_partial, but copies from user space (but on the alpha + * the same as csum_partial, but copies from user space (but on MIPS * we have just one address space, so this is identical to the above) + * + * this is obsolete and will go away. */ #define csum_partial_copy_fromuser csum_partial_copy /* + * this is a new version of the above that records errors it finds in *errp, + * but continues and zeros the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp); + +/* + * Fold a partial checksum without adding pseudo headers + */ +static inline unsigned short int csum_fold(unsigned int sum) +{ + unsigned int __res; + + __asm__(" + .set noat + srl $1,%0,16 + andi %0,0xffff + addu $1,%0 + srl %0,$1,16 # addup halfword carry + andi $1,0xffff + addu $1,%0 + nor %0,$0,$1 + .set at" + : "=r"(__res) + : "0" (sum) + : "$1"); + + return __res; +} + +/* * This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. * @@ -49,54 +81,48 @@ static inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { - unsigned short int sum; - unsigned long dummy1, dummy2; + unsigned int sum; + unsigned long dummy; /* - * 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. + * This is for 32-bit MIPS processors. */ - __asm__(" + __asm__ __volatile__(" .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) + lw %0,(%1) + subu %2,4 + #blez %2,2f + sll %2,2 # delay slot + + lw %3,4(%1) + addu %2,%1 # delay slot + addu %0,%3 + sltu $1,%0,%3 + lw %3,8(%1) addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - lw %2,12(%3) + addu %0,%3 + sltu $1,%0,%3 + lw %3,12(%1) addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 + addu %0,%3 + sltu $1,%0,%3 addu %0,$1 -1: lw %2,16(%3) - addu %1,4 - addu %0,%2 - sltu $1,%0,%2 - bne %1,%3,1b + +1: lw %3,16(%1) + addiu %1,4 + addu %0,%3 + sltu $1,%0,%3 + bne %2,%1,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) + : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy) + : "1" (iph), "2" (ihl) : "$1"); - return sum; + return csum_fold(sum); } /* @@ -120,57 +146,47 @@ addu %0,%4 sltu $1,%0,%4 addu %0,$1 + srl $1,%0,16 + andi %0,0xffff addu %0,$1 - sltu $1,%0,$1 + srl $1,%0,16 # addup halfword carry + andi %0,0xffff 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) + : "0" (daddr), "r"(saddr), +#ifdef __MIPSEL__ + "r" ((ntohs(len)<<16)+proto*256), +#else + "r" (((proto)<<16)+len), +#endif + "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) { +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ unsigned short int sum; __asm__(" .set noat srl $1,%0,16 + andi %0,0xffff addu %0,$1 sltu $1,%0,$1 + addu %0,$1 nor %0,$0,%0 - andi %0,0xffff .set at" : "=r"(sum) - : "r" (csum_partial(buff, len, 0)) + : "0" (csum_partial(buff, len, 0)) : "$1"); return sum; @@ -183,9 +199,7 @@ unsigned short proto, unsigned int sum) { - unsigned long scratch; - - __asm__(" + __asm__(" .set noreorder .set noat addu %0,%5 # proto (long in network byte order) @@ -234,14 +248,13 @@ addu %0,%1 sltu $1,%0,$1 .set noat - .set noreorder - " - : "=r" (sum), - "=r" (scratch) - : "r" (saddr), + .set noreorder" + : "=r" (sum), + "=r" (proto) + : "r" (saddr), "r" (daddr), - "0" (htonl((__u32) (len))), - "r" (htonl(proto)), + "0" (htonl((__u32) (len))), + "1" (htonl(proto)), "r"(sum) : "$1"); diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h --- v2.1.43/linux/include/asm-mips/cpu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/cpu.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,40 @@ +/* $Id: cpu.h,v 1.1 1997/06/06 09:38:41 ralf Exp $ + * cpu.h: Values of the PRId register used to match up + * various MIPS cpu types. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _MIPS_CPU_H +#define _MIPS_CPU_H + +/* + * Assigned values for the product ID register. In order to detect a + * certain CPU type exactly eventually additional registers may need to + * be examined. + */ +#define PRID_IMP_R2000 0x0100 +#define PRID_IMP_R3000 0x0200 +#define PRID_IMP_R6000 0x0300 +#define PRID_IMP_R4000 0x0400 +#define PRID_IMP_R6000A 0x0600 +#define PRID_IMP_R10000 0x0900 +#define PRID_IMP_R4300 0x0b00 +#define PRID_IMP_R8000 0x1000 +#define PRID_IMP_R4600 0x2000 +#define PRID_IMP_R4700 0x2100 +#define PRID_IMP_R4640 0x2200 +#define PRID_IMP_R4650 0x2200 /* Same as R4640 */ +#define PRID_IMP_R5000 0x2300 +#define PRID_IMP_SONIC 0x2400 +#define PRID_IMP_MAGIC 0x2500 +#define PRID_IMP_RM7000 0x2700 +#define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */ + +#define PRID_IMP_UNKNOWN 0xff00 + +#define PRID_REV_R4400 0x0040 +#define PRID_REV_R3000A 0x0030 +#define PRID_REV_R3000 0x0020 +#define PRID_REV_R2000A 0x0010 + +#endif /* !(_MIPS_CPU_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/current.h linux/include/asm-mips/current.h --- v2.1.43/linux/include/asm-mips/current.h Mon Dec 30 01:58:35 1996 +++ linux/include/asm-mips/current.h Thu Jun 26 12:33:39 1997 @@ -1,12 +1,48 @@ -#ifndef _MIPS_CURRENT_H -#define _MIPS_CURRENT_H +#ifndef __ASM_MIPS_CURRENT_H +#define __ASM_MIPS_CURRENT_H -/* Some architectures may want to do something "clever" here since - * this is the most frequently accessed piece of data in the entire - * kernel. For an example, see the Sparc implementation where an - * entire register is hard locked to contain the value of current. +#ifdef __LANGUAGE_C__ + +static inline struct task_struct *__get_current(void) +{ + struct task_struct *__current; + + __asm__("ori\t%0,$29,%1\n\t" + "xori\t%0,%1" + :"=r" (__current) + :"ir" (8191UL)); + + return __current; +} + +#define current __get_current() + +#endif /* __LANGUAGE_C__ */ +#ifdef __LANGUAGE_ASSEMBLY__ + +/* + * Get current task pointer + */ +#define GET_CURRENT(reg) \ + lui reg, %hi(kernelsp); \ + lw reg, %lo(kernelsp)(reg); \ + ori reg, 8191; \ + xori reg, 8191 + +/* + * Special variant for use by exception handlers when the stack pointer + * is not loaded. */ -extern struct task_struct *current_set[NR_CPUS]; -#define current (current_set[smp_processor_id()]) /* Current on this processor */ +#define _GET_CURRENT(reg) \ + lui reg, %hi(kernelsp); \ + .set push; \ + .set noreorder; \ + lw reg, %lo(kernelsp)(reg); \ + .set pop; \ + ori reg, 8191; \ + xori reg, 8191 + + +#endif -#endif /* !(_MIPS_CURRENT_H) */ +#endif /* __ASM_MIPS_CURRENT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/decstation.h linux/include/asm-mips/decstation.h --- v2.1.43/linux/include/asm-mips/decstation.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/decstation.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,254 @@ +/* + * Hardware info about DEC Personal DECStation systems (otherwise known + * as maxine or pmax (internal DEC codenames). + * + * 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 Paul M. Antoine, some code and definitions are + * by curteousy of Chris Fraser. + * + * This file is under construction - you were warned! + */ + +#ifndef __ASM_MIPS_PMAX_H +#define __ASM_MIPS_PMAX_H + +/* + * The addresses below are virtual address. The mappings are + * created on startup via wired entries in the tlb. + */ + +#define PMAX_LOCAL_IO_SPACE 0xe0000000 + +/* + * Motherboard regs (kseg1 addresses) + */ +#define PMAX_SSR_ADDR 0xbc040100 /* system support reg */ + +/* + * SSR defines + */ +#define PMAX_SSR_LEDMASK 0x00000001 /* power LED */ + +/* + * REX functions -- these are for the new TURBOchannel style ROMs + */ +#define REX_PROM_MAGIC 0x30464354 /* passed in a2 */ + +#define REX_GETBITMAP 0x84 /* get mem bitmap */ +#define REX_GETCHAR 0x24 /* getch() */ +#define REX_PUTCHAR 0x13 /* putch() */ +#define REX_HALT 0x9c /* halt the system */ +#define REX_PRINTF 0x30 /* printf() */ +#define REX_PUTS 0x2c /* puts() */ +#define REX_SLOTADDR 0x6c /* slotaddr */ + +#ifndef __LANGUAGE_ASSEMBLY__ + +extern __inline__ void pmax_set_led(unsigned int bits) +{ + volatile unsigned int *led_register = (unsigned int *) PMAX_SSR_ADDR; + + *led_register = bits & PMAX_SSR_LEDMASK; +} + +/* + * Glue code to call the PMAX boot proms. + */ +extern asmlinkage void pmax_printf(const char *); + +#endif + +/* + * These are just hacked out of the JAZZ ones, no ideas really. + */ +#define PMAX_KEYBOARD_ADDRESS 0xe0005000 +#define PMAX_KEYBOARD_DATA 0xe0005000 +#define PMAX_KEYBOARD_COMMAND 0xe0005001 + +#ifndef __LANGUAGE_ASSEMBLY__ + +typedef struct { + unsigned char data; + unsigned char command; +} pmax_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 pmax_keyboard_hardware + +#endif + +/* + * Serial ports on DEC - maybe! + */ + +#define PMAX_SERIAL1_BASE (unsigned int)0xe0006000 +#define PMAX_SERIAL2_BASE (unsigned int)0xe0007000 + +/* + * Dummy Device Address. Used in pmaxdma.c + */ + +#define PMAX_DUMMY_DEVICE 0xe000d000 + +/* + * PMAX 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 PMAX_TIMER_INTERVAL 0xe0000228 +#define PMAX_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 PMAX_DRAM_CONFIG 0xe00fffe0 + +/* + * PMAX interrupt control registers + */ +#define PMAX_IO_IRQ_SOURCE 0xe0100000 +#define PMAX_IO_IRQ_ENABLE 0xe0100002 + +/* + * PMAX interrupt enable bits + */ +#define PMAX_IE_PARALLEL (1 << 0) +#define PMAX_IE_FLOPPY (1 << 1) +#define PMAX_IE_SOUND (1 << 2) +#define PMAX_IE_VIDEO (1 << 3) +#define PMAX_IE_ETHERNET (1 << 4) +#define PMAX_IE_SCSI (1 << 5) +#define PMAX_IE_KEYBOARD (1 << 6) +#define PMAX_IE_MOUSE (1 << 7) +#define PMAX_IE_SERIAL1 (1 << 8) +#define PMAX_IE_SERIAL2 (1 << 9) + +/* + * PMAX Interrupt Level definitions + */ + +#define PMAX_TIMER_IRQ 0 +#define PMAX_KEYBOARD_IRQ 1 +#define PMAX_ETHERNET_IRQ 2 /* 15 */ +#define PMAX_SERIAL1_IRQ 3 +#define PMAX_SERIAL2_IRQ 4 +#define PMAX_PARALLEL_IRQ 5 +#define PMAX_FLOPPY_IRQ 6 /* needs to be consistent with floppy driver! */ + +/* + * PMAX 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 PMAX_SCSI_DMA 0 /* SCSI */ +#define PMAX_FLOPPY_DMA 1 /* FLOPPY */ +#define PMAX_AUDIOL_DMA 2 /* AUDIO L */ +#define PMAX_AUDIOR_DMA 3 /* AUDIO R */ + +/* + * PMAX R4030 MCT_ADR chip (DMA controller) + * Note: Virtual Addresses ! + */ + +#define PMAX_R4030_CONFIG 0xE0000000 /* R4030 config register */ +#define PMAX_R4030_REVISION 0xE0000008 /* same as PICA_ASIC_REVISION */ +#define PMAX_R4030_INV_ADDR 0xE0000010 /* Invalid Address register */ + +#define PMAX_R4030_TRSTBL_BASE 0xE0000018 /* Translation Table Base */ +#define PMAX_R4030_TRSTBL_LIM 0xE0000020 /* Translation Table Limit */ +#define PMAX_R4030_TRSTBL_INV 0xE0000028 /* Translation Table Invalidate */ + +#define PMAX_R4030_CACHE_MTNC 0xE0000030 /* Cache Maintenance */ +#define PMAX_R4030_R_FAIL_ADDR 0xE0000038 /* Remote Failed Address */ +#define PMAX_R4030_M_FAIL_ADDR 0xE0000040 /* Memory Failed Adresss */ + +#define PMAX_R4030_CACHE_PTAG 0xE0000048 /* I/O Cache Physical Tag */ +#define PMAX_R4030_CACHE_LTAG 0xE0000050 /* I/O Cache Logical Tag */ +#define PMAX_R4030_CACHE_BMASK 0xE0000058 /* I/O Cache Byte Mask */ +#define PMAX_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 PMAX_R4030_REM_SPEED 0xE0000070 /* 16 Remote Speed Registers */ + /* 0xE0000070,78,80... 0xE00000E8 */ +#define PMAX_R4030_IRQ_ENABLE 0xE00000E8 /* Internal Interrupt Enable */ + +#define PMAX_R4030_IRQ_SOURCE 0xE0000200 /* Interrupt Source Reg */ +#define PMAX_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__("nop; nop; nop; nop;"); + return ret; +} + +extern inline unsigned int r4030_read_reg32(unsigned addr) { + unsigned int ret = *((volatile unsigned int *)addr); + __asm__ __volatile__("nop; nop; nop; nop;"); + return ret; +} + +extern inline void r4030_write_reg16(unsigned addr, unsigned val) { + *((volatile unsigned short *)addr) = val; + __asm__ __volatile__("nop; nop; nop; nop;"); +} + +extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) { + *((volatile unsigned int *)addr) = val; + __asm__ __volatile__("nop; nop; nop; nop;"); +} + +#endif /* !LANGUAGE_ASSEMBLY__ */ + + +#endif /* __ASM_MIPS_PMAX_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h --- v2.1.43/linux/include/asm-mips/delay.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/delay.h Thu Jun 26 12:33:39 1997 @@ -4,11 +4,9 @@ extern __inline__ void __delay(int loops) { __asm__ __volatile__ ( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "1:\tbne\t$0,%0,1b\n\t" - "subu\t%0,%0,1\n\t" - ".set\tat\n\t" + ".set\tnoreorder\n" + "1:\tbnez\t%0,1b\n\t" + "subu\t%0,1\n\t" ".set\treorder" :"=r" (loops) :"0" (loops)); @@ -24,15 +22,23 @@ * first constant multiplications gets optimized away if the delay is * a constant) */ -extern __inline__ void udelay(unsigned long usecs) +extern __inline__ void __udelay(unsigned long usecs, unsigned long lps) { usecs *= 0x000010c6; /* 2**32 / 1000000 */ __asm__("multu\t%0,%1\n\t" "mfhi\t%0" :"=r" (usecs) - :"0" (usecs),"r" (loops_per_sec)); + :"0" (usecs),"r" (lps)); __delay(usecs); } + +#ifdef __SMP__ +#define __udelay_val cpu_data[smp_processor_id()].udelay_val +#else +#define __udelay_val loops_per_sec +#endif + +#define udelay(usecs) __udelay((usecs),__udelay_val) /* * The different variants for 32/64 bit are pure paranoia. The typical diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/deskstation.h linux/include/asm-mips/deskstation.h --- v2.1.43/linux/include/asm-mips/deskstation.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/deskstation.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,15 @@ +/* + * SNI specific 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) 1997 by Ralf Baechle + */ +#ifndef __ASM_MIPS_DESKSTATION_H +#define __ASM_MIPS_DESKSTATION_H + +#define RPC44_PORT_BASE 0xe2000000 + +#endif /* __ASM_MIPS_DESKSTATION_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/dma.h linux/include/asm-mips/dma.h --- v2.1.43/linux/include/asm-mips/dma.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/dma.h Thu Jun 26 12:33:39 1997 @@ -5,14 +5,15 @@ * 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 + * and can only be used for expansion cards. Onboard DMA controllers, such * as the R4030 on Jazz boards behave totally different! */ #ifndef __ASM_MIPS_DMA_H #define __ASM_MIPS_DMA_H -#include /* need byte IO */ +#include +#include /* need byte IO */ #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER @@ -74,12 +75,16 @@ #define MAX_DMA_CHANNELS 8 /* - * The maximum address that we can perform a DMA transfer to on this platform - * This describes 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 Magnums. + * The maximum address in KSEG0 that we can perform a DMA transfer to on this + * platform. This describes 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 Magnums. */ -#define MAX_DMA_ADDRESS 0x1000000 +#ifndef CONFIG_SGI +#define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) +#else +#define MAX_DMA_ADDRESS (~0UL) +#endif /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ @@ -275,10 +280,5 @@ /* These are in kernel/dma.c: */ 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), 1) #endif /* __ASM_MIPS_DMA_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- v2.1.43/linux/include/asm-mips/elf.h Sun Aug 4 04:12:40 1996 +++ linux/include/asm-mips/elf.h Thu Jun 26 12:33:39 1997 @@ -1,12 +1,9 @@ #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 +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[ELF_NGREG]; @@ -17,17 +14,30 @@ /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(x) ((x) == EM_MIPS) +#define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_MIPS_RS4_BE) /* * These are used to set parameters in the core dumps. * FIXME(eric) I don't know what the correct endianness to use is. */ #define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB; +#ifdef __MIPSEB__ +#define ELF_DATA ELFDATA2MSB; +#elif __MIPSEL__ +#define ELF_DATA ELFDATA2LSB; +#endif #define ELF_ARCH EM_MIPS #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 4096 + +#define ELF_CORE_COPY_REGS(_dest,_regs) \ + memcpy((char *) &_dest, (char *) _regs, \ + sizeof(struct pt_regs)); + +/* See comments in asm-alpha/elf.h, this is the same thing + * on the MIPS. + */ +#define ELF_PLAT_INIT(_r) _r->regs[2] = 0; #endif /* __ASM_MIPS_ELF_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h --- v2.1.43/linux/include/asm-mips/errno.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/errno.h Thu Jun 26 12:33:39 1997 @@ -137,6 +137,22 @@ #define EINPROGRESS 150 /* Operation now in progress */ #define ESTALE 151 /* Stale NFS file handle */ #define ECANCELED 158 /* AIO operation canceled */ + +/* + * These error are Linux extensions. + */ +#define ENOMEDIUM 159 /* No medium found */ +#define EMEDIUMTYPE 160 /* Wrong medium type */ + +/* + * IRIX 5 error number start from 1000. + * Stupid enough; ECANCELED gets redefined with a different value ... +#define ECANCELED 1000 + */ + +/* + * IRIX 4 compatibility error numbers. + */ #define EDQUOT 1133 /* Quota exceeded */ #define ENFSREMOTE 1134 /* ??? */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h --- v2.1.43/linux/include/asm-mips/fcntl.h Sat Sep 21 23:41:32 1996 +++ linux/include/asm-mips/fcntl.h Thu Jun 26 12:33:39 1997 @@ -52,10 +52,10 @@ typedef struct flock { short l_type; short l_whence; - off_t l_start; - off_t l_len; + __kernel_off_t l_start; + __kernel_off_t l_len; long l_sysid; /* XXXXXXXXXXXXXXXXXXXXXXXXX */ - pid_t l_pid; + __kernel_pid_t l_pid; long pad[4]; /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */ } flock_t; diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v2.1.43/linux/include/asm-mips/floppy.h Sat Sep 28 12:05:41 1996 +++ linux/include/asm-mips/floppy.h Thu Jun 26 12:33:39 1997 @@ -10,6 +10,7 @@ #ifndef __ASM_MIPS_FLOPPY_H #define __ASM_MIPS_FLOPPY_H +#include #include #include #include @@ -30,7 +31,6 @@ #define fd_get_dma_residue() feature->fd_get_dma_residue() #define fd_enable_irq() feature->fd_enable_irq() #define fd_disable_irq() feature->fd_disable_irq() -#define fd_cacheflush(addr, size) feature->fd_cacheflush((void *)addr, size) #define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \ SA_INTERRUPT|SA_SAMPLE_RANDOM, \ "floppy", NULL) @@ -38,7 +38,21 @@ #define MAX_BUFFER_SECTORS 24 -static unsigned long mips_dma_mem_alloc(unsigned long size) +/* Pure 2^n version of get_order */ +extern __inline__ int __get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} + +extern __inline__ unsigned long mips_dma_mem_alloc(unsigned long size) { int order = __get_order(size); unsigned long mem; @@ -46,38 +60,36 @@ mem = __get_dma_pages(GFP_KERNEL,order); if(!mem) return 0; - if (boot_info.machtype == MACH_ACER_PICA_61 || - boot_info.machtype == MACH_MIPS_MAGNUM_4000 || - boot_info.machtype == MACH_OLIVETTI_M700) +#ifdef CONFIG_MIPS_JAZZ + if (mips_machgroup == MACH_GROUP_JAZZ) vdma_alloc(PHYSADDR(mem), size); +#endif return mem; } -static void mips_dma_mem_free(unsigned long addr, unsigned long size) +extern __inline__ void mips_dma_mem_free(unsigned long addr, unsigned long size) { - if (boot_info.machtype == MACH_ACER_PICA_61 || - boot_info.machtype == MACH_MIPS_MAGNUM_4000 || - boot_info.machtype == MACH_OLIVETTI_M700) +#ifdef CONFIG_MIPS_JAZZ + if (mips_machgroup == MACH_GROUP_JAZZ) vdma_free(PHYSADDR(addr)); +#endif free_pages(addr, __get_order(size)); } -#define fd_dma_mem_alloc(mem,size) mips_dma_mem_alloc(mem,size) -#define fd_dma_mem_free(mem) mips_dma_mem_free(mem) +#define fd_dma_mem_alloc(size) mips_dma_mem_alloc(size) +#define fd_dma_mem_free(mem,size) mips_dma_mem_free(mem,size) /* * And on Mips's the CMOS info fails also ... * * FIXME: This information should come from the ARC configuration tree - * or wherever a particular machine has stored this ... + * or whereever a particular machine has stored this ... */ #define FLOPPY0_TYPE 4 /* this is wrong for the Olli M700, but who cares... */ #define FLOPPY1_TYPE 0 -#define FDC1 ((boot_info.machtype == MACH_ACER_PICA_61 || \ - boot_info.machtype == MACH_MIPS_MAGNUM_4000 || \ - boot_info.machtype == MACH_OLIVETTI_M700) ? \ - 0xe0003000 : 0x3f0) +#define FDC1 ((mips_machgroup == MACH_GROUP_JAZZ) ? \ + JAZZ_FDC_BASE : 0x3f0) static int FDC2=-1; #define N_FDC 1 /* do you *really* want a second controller? */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h --- v2.1.43/linux/include/asm-mips/hardirq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/hardirq.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,24 @@ +#ifndef __ASM_MIPS_HARDIRQ_H +#define __ASM_MIPS_HARDIRQ_H + +#include + +extern unsigned int local_irq_count[NR_CPUS]; +#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) + +#ifndef __SMP__ + +#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_endlock(cpu) do { } while (0) + +#define hardirq_enter(cpu) (local_irq_count[cpu]++) +#define hardirq_exit(cpu) (local_irq_count[cpu]--) + +#define synchronize_irq() do { } while (0) + +#else + +#error No habla MIPS SMP + +#endif /* __SMP__ */ +#endif /* __ASM_MIPS_HARDIRQ_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h --- v2.1.43/linux/include/asm-mips/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/ide.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,119 @@ +/* + * linux/include/asm-mips/ide.h + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + */ + +/* + * This file contains the MIPS architecture specific IDE code. + */ + +#ifndef __ASM_MIPS_IDE_H +#define __ASM_MIPS_IDE_H + +#ifdef __KERNEL__ + +typedef unsigned short ide_ioreg_t; + +#ifndef MAX_HWIFS +#define MAX_HWIFS 4 +#endif + +#define ide_sti() sti() + +static __inline__ int ide_default_irq(ide_ioreg_t base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + case 0x168: return 10; + default: + return 0; + } +} + +static __inline__ ide_ioreg_t ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0x1f0; + case 1: return 0x170; + case 2: return 0x1e8; + case 3: return 0x168; + default: + return 0; + } +} + +static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) +{ + ide_ioreg_t port = base; + int i = 8; + + while (i--) + *p++ = port++; + *p++ = base + 0x206; + if (irq != NULL) + *irq = 0; +} + +typedef union { + unsigned all : 8; /* all of the bits together */ + struct { + unsigned head : 4; /* always zeros here */ + unsigned unit : 1; /* drive select number, 0 or 1 */ + unsigned bit5 : 1; /* always 1 */ + unsigned lba : 1; /* using LBA instead of CHS */ + unsigned bit7 : 1; /* always 1 */ + } b; + } select_t; + +static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *device, void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static __inline__ void ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) +{ + request_region(from, extent, name); +} + +static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +/* + * The following are not needed for the non-m68k ports + */ +static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port) +{ + return(1); +} + +static __inline__ void ide_fix_driveid(struct hd_driveid *id) +{ +} + +static __inline__ void ide_release_lock (int *ide_lock) +{ +} + +static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) +{ +} + +#endif /* __KERNEL__ */ + +#endif /* __ASM_MIPS_IDE_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/init.h linux/include/asm-mips/init.h --- v2.1.43/linux/include/asm-mips/init.h Wed Apr 16 14:15:00 1997 +++ linux/include/asm-mips/init.h Thu Jun 26 12:33:39 1997 @@ -1,5 +1,5 @@ -#ifndef _MIPS_INIT_H -#define _MIPS_INIT_H +#ifndef __ASM_MIPS_INIT_H +#define __ASM_MIPS_INIT_H /* Throwing the initialization code and data out is not supported yet... */ @@ -11,4 +11,4 @@ #define __FINIT #define __INITDATA -#endif +#endif /* __ASM_MIPS_INIT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/inst.h linux/include/asm-mips/inst.h --- v2.1.43/linux/include/asm-mips/inst.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/inst.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,304 @@ +/* + * Format of an instruction in memory. + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_INST_H +#define __ASM_MIPS_INST_H + +/* + * Major opcodes; before MIPS IV cop1x was called cop3. + */ +enum major_op { + spec_op, bcond_op, j_op, jal_op, + beq_op, bne_op, blez_op, bgtz_op, + addi_op, addiu_op, slti_op, sltiu_op, + andi_op, ori_op, xori_op, lui_op, + cop0_op, cop1_op, cop2_op, cop1x_op, + beql_op, bnel_op, blezl_op, bgtzl_op, + daddi_op, daddiu_op, ldl_op, ldr_op, + major_1c_op, major_1d_op, major_1e_op, major_1f_op, + lb_op, lh_op, lwl_op, lw_op, + lbu_op, lhu_op, lwr_op, lwu_op, + sb_op, sh_op, swl_op, sw_op, + sdl_op, sdr_op, swr_op, cache_op, + ll_op, lwc1_op, lwc2_op, pref_op, + lld_op, ldc1_op, ldc2_op, ld_op, + sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */ + scd_op, sdc1_op, sdc2_op, sd_op +}; + +/* + * func field of spec opcode. + */ +enum spec_op { + sll_op, movc_op, srl_op, sra_op, + sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */ + jr_op, jalr_op, movz_op, movn_op, + syscall_op, break_op, spim_op, sync_op, + mfhi_op, mthi_op, mflo_op, mtlo_op, + dsllv_op, spec2_unused_op, dsrlv_op, dsrav_op, + mult_op, multu_op, div_op, divu_op, + dmult_op, dmultu_op, ddiv_op, ddivu_op, + add_op, addu_op, sub_op, subu_op, + and_op, or_op, xor_op, nor_op, + spec3_unused_op, spec4_unused_op, slt_op, sltu_op, + dadd_op, daddu_op, dsub_op, dsubu_op, + tge_op, tgeu_op, tlt_op, tltu_op, + teq_op, spec5_unused_op, tne_op, spec6_unused_op, + dsll_op, spec7_unused_op, dsrl_op, dsra_op, + dsll32_op, spec8_unused_op, dsrl32_op, dsra32_op +}; + +/* + * rt field of bcond opcodes. + */ +enum rt_op { + bltz_op, bgez_op, bltzl_op, bgezl_op, + spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07, + tgei_op, tgeiu_op, tlti_op, tltiu_op, + teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op, + bltzal_op, bgezal_op, bltzall_op, bgezall_op + /* + * The others (0x14 - 0x1f) are unused. + */ +}; + +/* + * rs field of cop opcodes. + */ +enum cop_op { + mfc_op = 0x00, dmfc_op = 0x01, + cfc_op = 0x02, mtc_op = 0x04, + dmtc_op = 0x05, ctc_op = 0x06, + bc_op = 0x08, cop_op = 0x10, + copm_op = 0x18 +}; + +/* + * func field of cop0 coi opcodes. + */ +enum cop0_coi_func { + tlbr_op = 0x01, tlbwi_op = 0x02, + tlbwr_op = 0x06, tlbp_op = 0x08, + rfe_op = 0x10, eret_op = 0x18 +}; + +/* + * func field of cop0 com opcodes. + */ +enum cop0_com_func { + tlbr1_op = 0x01, tlbw_op = 0x02, + tlbp1_op = 0x08, dctr_op = 0x09, + dctw_op = 0x0a +}; + +/* + * fmt field of cop1 opcodes. + */ +enum cop1_fmt { + s_fmt, d_fmt, e_fmt, q_fmt, + w_fmt, l_fmt +}; + +/* + * func field of cop1 instructions using d, s or w format. + */ +enum cop1_sdw_func { + fadd_op = 0x00, fsub_op = 0x01, + fmul_op = 0x02, fdiv_op = 0x03, + fsqrt_op = 0x04, fabs_op = 0x05, + fmov_op = 0x06, fneg_op = 0x07, + froundl_op = 0x08, ftruncl_op = 0x09, + fceill_op = 0x0a, ffloorl_op = 0x0b, + fround_op = 0x0c, ftrunc_op = 0x0d, + fceil_op = 0x0e, ffloor_op = 0x0f, + fmovc_op = 0x11, fmovz_op = 0x12, + fmovn_op = 0x13, frecip_op = 0x15, + frsqrt_op = 0x16, fcvts_op = 0x20, + fcvtd_op = 0x21, fcvte_op = 0x22, + fcvtw_op = 0x24, fcvtl_op = 0x25, + fcmp_op = 0x30 +}; + +/* + * func field of cop1x opcodes (MIPS IV). + */ +enum cop1x_func { + lwxc1_op = 0x00, ldxc1_op = 0x01, + pfetch_op = 0x07, swxc1_op = 0x08, + sdxc1_op = 0x09, madd_s_op = 0x20, + madd_d_op = 0x21, madd_e_op = 0x22, + msub_s_op = 0x28, msub_d_op = 0x29, + msub_e_op = 0x2a, nmadd_s_op = 0x30, + nmadd_d_op = 0x31, nmadd_e_op = 0x32, + nmsub_s_op = 0x38, nmsub_d_op = 0x39, + nmsub_e_op = 0x3a +}; + +/* + * func field for mad opcodes (MIPS IV). + */ +enum mad_func { + madd_op = 0x08, msub_op = 0x0a, + nmadd_op = 0x0c, nmsub_op = 0x0e +}; + +/* + * Damn ... bitfields depend from byteorder :-( + */ +#ifdef __MIPSEB__ +struct j_format { /* Jump format */ + unsigned int opcode : 6; + unsigned int target : 26; +}; + +struct i_format { /* Immediate format (addi, lw, ...) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + signed int simmediate : 16; +}; + +struct u_format { /* Unsigned immediate format (ori, xori, ...) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int uimmediate : 16; +}; + +struct c_format { /* Cache (>= R6000) format */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int c_op : 3; + unsigned int cache : 2; + unsigned int simmediate : 16; +}; + +struct r_format { /* Register format */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct p_format { /* Performance counter format (R10000) */ + unsigned int opcode : 6; + unsigned int rs : 5; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct f_format { /* FPU register format */ + unsigned int opcode : 6; + unsigned int : 1; + unsigned int fmt : 4; + unsigned int rt : 5; + unsigned int rd : 5; + unsigned int re : 5; + unsigned int func : 6; +}; + +struct ma_format { /* FPU multipy and add format (MIPS IV) */ + unsigned int opcode : 6; + unsigned int fr : 5; + unsigned int ft : 5; + unsigned int fs : 5; + unsigned int fd : 5; + unsigned int func : 4; + unsigned int fmt : 2; +}; + +#elif defined(__MIPSEL__) + +struct j_format { /* Jump format */ + unsigned int target : 26; + unsigned int opcode : 6; +}; + +struct i_format { /* Immediate format */ + signed int simmediate : 16; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct u_format { /* Unsigned immediate format */ + unsigned int uimmediate : 16; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct c_format { /* Cache (>= R6000) format */ + unsigned int simmediate : 16; + unsigned int cache : 2; + unsigned int c_op : 3; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct r_format { /* Register format */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct p_format { /* Performance counter format (R10000) */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int rs : 5; + unsigned int opcode : 6; +}; + +struct f_format { /* FPU register format */ + unsigned int func : 6; + unsigned int re : 5; + unsigned int rd : 5; + unsigned int rt : 5; + unsigned int fmt : 4; + unsigned int : 1; + unsigned int opcode : 6; +}; + +struct ma_format { /* FPU multipy and add format (MIPS IV) */ + unsigned int fmt : 2; + unsigned int func : 4; + unsigned int fd : 5; + unsigned int fs : 5; + unsigned int ft : 5; + unsigned int fr : 5; + unsigned int opcode : 6; +}; + +#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" +#endif + +union mips_instruction { + unsigned int word; + unsigned short halfword[2]; + unsigned char byte[4]; + struct j_format j_format; + struct i_format i_format; + struct u_format u_format; + struct c_format c_format; + struct r_format r_format; + struct f_format f_format; + struct ma_format ma_format; +}; + +#endif /* __ASM_MIPS_INST_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/io.h linux/include/asm-mips/io.h --- v2.1.43/linux/include/asm-mips/io.h Sun Oct 6 22:55:48 1996 +++ linux/include/asm-mips/io.h Thu Jun 26 12:33:39 1997 @@ -1,14 +1,21 @@ #ifndef __ASM_MIPS_IO_H #define __ASM_MIPS_IO_H +/* + * Slowdown I/O port space accesses for antique hardware. + */ +#undef CONF_SLOWDOWN_IO + #include -#include +#include /* * This file contains the definitions for the MIPS counterpart of the * x86 in/out instructions. This heap of macros and C results in much - * better code than the approach of doing it in plain C, though that's - * probably not needed. + * better code than the approach of doing it in plain C. The macros + * result in code that is to fast for certain hardware. On the other + * side the performance of the string functions should be improved for + * sake of certain devices like EIDE disks that do highspeed polled I/O. * * Ralf * @@ -33,6 +40,7 @@ * I feel a bit unsafe about using 0x80 (should be safe, though) * * Linus + * */ #define __SLOW_DOWN_IO \ @@ -40,11 +48,15 @@ "sb\t$0,0x80(%0)" \ : : "r" (PORT_BASE)); +#ifdef CONF_SLOWDOWN_IO #ifdef REALLY_SLOW_IO #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } #else #define SLOW_DOWN_IO __SLOW_DOWN_IO #endif +#else +#define SLOW_DOWN_IO +#endif /* * Change virtual addresses to physical addresses and vv. @@ -52,44 +64,106 @@ */ extern inline unsigned long virt_to_phys(volatile void * address) { - return (unsigned long) address - KSEG0; + return PHYSADDR(address); } extern inline void * phys_to_virt(unsigned long address) { - return (void *) address + KSEG0; + return (void *)KSEG0ADDR(address); } +extern void * ioremap(unsigned long phys_addr, unsigned long size); +extern void iounmap(void *addr); + /* * 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 +extern inline unsigned long virt_to_bus(volatile void * address) +{ + return PHYSADDR(address); +} + +extern inline void * bus_to_virt(unsigned long address) +{ + return (void *)KSEG0ADDR(address); +} + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped + * for the processor. + */ +extern unsigned long isa_slot_offset; /* * 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. + * + * On MIPS, we have the whole physical address space mapped at all + * times, so "ioremap()" and "iounmap()" do not need to do anything. + * (This isn't true for all machines but we still handle these cases + * with wired TLB entries anyway ...) + * + * We cheat a bit and always return uncachable areas until we've fixed + * the drivers to handle caching properly. + */ +extern inline void * ioremap(unsigned long offset, unsigned long size) +{ + return (void *) KSEG1ADDR(offset); +} + +/* + * This one maps high address device memory and turns off caching for that area. + * it's useful if some control registers are in such an area and write combining + * or read caching is not desirable: + */ +extern inline void * ioremap_nocache (unsigned long offset, unsigned long size) +{ + return (void *) KSEG1ADDR(offset); +} + +extern inline void iounmap(void *addr) +{ +} + +/* + * XXX We need system specific versions of these to handle EISA address bits + * 24-31 on SNI. */ -#define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) +#define readb(addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr))) +#define readw(addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr))) +#define readl(addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(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 writeb(b,addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr)) = (b)) +#define writew(b,addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr)) = (b)) +#define writel(b,addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(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)) +#define memset_io(a,b,c) memset((void *)(isa_slot_offset + (unsigned long)a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(isa_slot_offset + (unsigned long)(b)),(c)) +#define memcpy_toio(a,b,c) memcpy((void *)(isa_slot_offset + (unsigned long)(a)),(b),(c)) /* - * Again, MIPS does not require mem IO specific function. + * We don't have csum_partial_copy_fromio() yet, so we cheat here and + * just copy it. The net code will then do the checksum later. */ +#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len)) -#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),(void *)(b),(c),(d)) +static inline int check_signature(unsigned long io_addr, + const unsigned char *signature, int length) +{ + int retval = 0; + do { + if (readb(io_addr) != *signature) + goto out; + io_addr++; + signature++; + length--; + } while (length); + retval = 1; +out: + return retval; +} /* * Talk about misusing macros.. @@ -113,10 +187,10 @@ extern __inline__ t __in##s(unsigned int port) { t _v; /* - * Useless nops will be removed by the assembler + * Required nops will be inserted by the assembler */ #define __IN2(m) \ -__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\tnop" +__asm__ __volatile__ ("l" #m "\t%0,%1(%2)" #define __IN(t,m,s) \ __IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \ @@ -128,10 +202,11 @@ extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) { #define __INS2(m) \ +if (count) \ __asm__ __volatile__ ( \ ".set\tnoreorder\n\t" \ ".set\tnoat\n" \ - "1:\tl" #m "u\t$1,%4(%5)\n\t" \ + "1:\tl" #m "\t$1,%4(%5)\n\t" \ "subu\t%1,1\n\t" \ "s" #m "\t$1,(%0)\n\t" \ "bne\t$0,%1,1b\n\t" \ @@ -153,14 +228,15 @@ extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) { #define __OUTS2(m) \ +if (count) \ __asm__ __volatile__ ( \ ".set\tnoreorder\n\t" \ ".set\tnoat\n" \ - "1:\tl" #m "u\t$1,(%0)\n\t" \ - "subu\t%1,%1,1\n\t" \ + "1:\tl" #m "\t$1,(%0)\n\t" \ + "subu\t%1,1\n\t" \ "s" #m "\t$1,%4(%5)\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" diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h --- v2.1.43/linux/include/asm-mips/ioctl.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/ioctl.h Thu Jun 26 12:33:39 1997 @@ -1,3 +1,12 @@ +/* + * Linux ioctl() stuff. + * + * 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, 1996 by Ralf Baechle + */ #ifndef __ASM_MIPS_IOCTL_H #define __ASM_MIPS_IOCTL_H diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h --- v2.1.43/linux/include/asm-mips/ioctls.h Wed May 8 00:32:41 1996 +++ linux/include/asm-mips/ioctls.h Thu Jun 26 12:33:39 1997 @@ -1,8 +1,21 @@ +/* + * ioctls for Linux/MIPS. + * + * 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, 1996 by Ralf Baechle + */ #ifndef __ASM_MIPS_IOCTLS_H #define __ASM_MIPS_IOCTLS_H #include +#if defined(__USE_MISC) || defined (__KERNEL__) +#define tIOC ('t' << 8) +#endif + #define TCGETA 0x5401 #define TCSETA 0x5402 #define TCSETAW 0x5403 @@ -39,15 +52,18 @@ #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 TIOCSETD (tIOC | 1) +#define TIOCGETD (tIOC | 0) #define FIOCLEX 0x6601 #define FIONCLEX 0x6602 /* these numbers need to be adjusted. */ #define FIOASYNC 0x667d #define FIONBIO 0x667e - /* 116-117 compat */ +#if defined(__USE_MISC) || defined (__KERNEL__) +#define TIOCGLTC (tIOC | 116) /* get special local chars */ +#define TIOCSLTC (tIOC | 117) /* set special local chars */ +#endif #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 */ @@ -55,6 +71,12 @@ #define FIONREAD 0x467f #define TIOCINQ FIONREAD +#if defined(__USE_MISC) || defined (__KERNEL__) +#define TIOCGETP (tIOC | 8) +#define TIOCSETP (tIOC | 9) +#define TIOCSETN (tIOC | 10) /* TIOCSETP wo flush */ +#endif + #if 0 #define TIOCSETA _IOW('t', 20, struct termios) /* set termios struct */ #define TIOCSETAW _IOW('t', 21, struct termios) /* drain output, set */ @@ -84,217 +106,9 @@ #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 B460800 0010004 -#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 +#define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */ +#define TIOCSBRK 0x5491 /* BSD compatibility */ +#define TIOCCBRK 0x5492 /* BSD compatibility */ #endif /* __ASM_MIPS_IOCTLS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ipc.h linux/include/asm-mips/ipc.h --- v2.1.43/linux/include/asm-mips/ipc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/ipc.h Thu Jun 26 12:33:39 1997 @@ -0,0 +1,29 @@ +#ifndef __ASM_MIPS_IPC_H +#define __ASM_MIPS_IPC_H + +/* + * These are used to wrap system calls on MIPS. + * + * See arch/mips/kernel/sysmips.c for ugly details.. + * FIXME: split up into ordinary syscalls ... + */ +struct ipc_kludge { + struct msgbuf *msgp; + long msgtyp; +}; + +#define SEMOP 1 +#define SEMGET 2 +#define SEMCTL 3 +#define MSGSND 11 +#define MSGRCV 12 +#define MSGGET 13 +#define MSGCTL 14 +#define SHMAT 21 +#define SHMDT 22 +#define SHMGET 23 +#define SHMCTL 24 + +#define IPCCALL(version,op) ((version)<<16 | (op)) + +#endif /* __ASM_MIPS_IPC_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h --- v2.1.43/linux/include/asm-mips/irq.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/irq.h Thu Jun 26 12:33:39 1997 @@ -15,8 +15,12 @@ /* * Actually this is a lie but we hide the local device's interrupts ... */ -#define NR_IRQS 16 +#define NR_IRQS 64 +#define TIMER_IRQ 0 + +struct irqaction; +extern int setup_x86_irq(int irq, struct irqaction * new); extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h --- v2.1.43/linux/include/asm-mips/jazz.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/jazz.h Thu Jun 26 12:33:39 1997 @@ -9,7 +9,6 @@ * * This file is a mess. It really needs some reorganisation! */ - #ifndef __ASM_MIPS_JAZZ_H #define __ASM_MIPS_JAZZ_H @@ -87,6 +86,16 @@ #endif /* + * Base address of the Sonic Ethernet adapter in Jazz machines. + */ +#define JAZZ_ETHERNET_BASE 0xe0001000 + +/* + * Base address of the 53C94 SCSI hostadapter in Jazz machines. + */ +#define JAZZ_SCSI_BASE 0xe0002000 + +/* * 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... @@ -196,7 +205,7 @@ */ #define JAZZ_TIMER_IRQ 0 #define JAZZ_KEYBOARD_IRQ 1 -#define JAZZ_ETHERNET_IRQ 2 /* 15 */ +#define JAZZ_ETHERNET_IRQ 13 #define JAZZ_SERIAL1_IRQ 3 #define JAZZ_SERIAL2_IRQ 4 #define JAZZ_PARALLEL_IRQ 5 @@ -245,66 +254,63 @@ #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_INVAL_ADDR 0xE0000010 /* Invalid address Register */ +#define JAZZ_R4030_IRQ_SOURCE 0xE0000200 /* Interrupt Source Register */ #define JAZZ_R4030_I386_ERROR 0xE0000208 /* i386/EISA Bus Error */ +/* + * Virtual (E)ISA controller address + */ +#define JAZZ_EISA_IRQ_ACK 0xE0000238 /* EISA interrupt acknowledge */ /* * Access the R4030 DMA and I/O Controller */ #ifndef __LANGUAGE_ASSEMBLY__ -extern inline unsigned short r4030_read_reg16(unsigned addr) { +extern inline void r4030_delay(void) +{ +__asm__ __volatile__( + ".set\tnoreorder\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\treorder"); +} + +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"); + r4030_delay(); return ret; } -extern inline unsigned int r4030_read_reg32(unsigned addr) { +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"); + r4030_delay(); return ret; } -extern inline void r4030_write_reg16(unsigned addr, unsigned val) { +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"); + r4030_delay(); } -extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) { +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"); + r4030_delay(); } #endif /* !LANGUAGE_ASSEMBLY__ */ -#define JAZZ_FDC_BASE 0xe0003000 +#define JAZZ_FDC_BASE 0xe0003000 +#define JAZZ_RTC_BASE 0xe0004000 +#define JAZZ_PORT_BASE 0xe2000000 -#define JAZZ_RTC_BASE 0xe0004000 +#define JAZZ_EISA_BASE 0xe3000000 #endif /* __ASM_MIPS_JAZZ_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v2.1.43/linux/include/asm-mips/jazzdma.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/jazzdma.h Thu Jun 26 12:33:39 1997 @@ -1,14 +1,12 @@ /* * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support */ - -#ifndef __ASM_JAZZDMA_H -#define __ASM_JAZZDMA_H +#ifndef __ASM_MIPS_JAZZDMA_H +#define __ASM_MIPS_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); @@ -76,8 +74,9 @@ #define R4030_MEM_INTR (1<<9) #define R4030_ADDR_INTR (1<<10) -/* channel mode register bits */ - +/* + * 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) @@ -93,4 +92,4 @@ #define R4030_MODE_BURST (1<<6) /* Rev. 2 only */ #define R4030_MODE_FAST_ACK (1<<7) /* Rev. 2 only */ -#endif /* __ASM_JAZZDMA_H */ +#endif /* __ASM_MIPS_JAZZDMA_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.1.43/linux/include/asm-mips/keyboard.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-mips/keyboard.h Thu Jun 26 12:33:39 1997 @@ -1,20 +1,22 @@ /* - * linux/include/asm-mips/keyboard.h + * CPU specific parts of the keyboard driver * - * Created 3 Nov 1996 by Geert Uytterhoeven - */ - -/* - * This file contains the mips architecture specific keyboard 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. + * + * This file is a mess. Put on your peril sensitive glasses. + * + * $Id: keyboard.h,v 1.4 1997/06/16 00:31:46 ralf Exp $ */ - -#ifndef __ASMMIPS_KEYBOARD_H -#define __ASMMIPS_KEYBOARD_H +#ifndef __ASM_MIPS_KEYBOARD_H +#define __ASM_MIPS_KEYBOARD_H #ifdef __KERNEL__ -#define KEYBOARD_IRQ 1 -#define DISABLE_KBD_DURING_INTERRUPTS 0 +#include +#include +#include extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -33,8 +35,203 @@ #define kbd_leds pckbd_leds #define kbd_init_hw pckbd_init_hw -#define INIT_KBD +/* + * The default IO slowdown is doing 'inb()'s from 0x61, which should be + * safe. But as that is the keyboard controller chip address, we do our + * slowdowns here by doing short jumps: the keyboard controller should + * be able to keep up + */ +#define REALLY_SLOW_IO +#define SLOW_IO_BY_JUMPING +#include + +/* + * keyboard controller registers + */ +#define KBD_STATUS_REG (unsigned int) 0x64 +#define KBD_CNTL_REG (unsigned int) 0x64 +#define KBD_DATA_REG (unsigned int) 0x60 + +#ifdef CONFIG_SGI +#include +#include +#endif +#include +#include + +#ifdef CONFIG_SGI +#define KEYBOARD_IRQ 20 +#else +/* Not true for Jazz machines, we cheat a bit for 'em. */ +#define KEYBOARD_IRQ 1 +#endif + +#ifdef CONFIG_SGI +#define DISABLE_KBD_DURING_INTERRUPTS 1 +#else +#define DISABLE_KBD_DURING_INTERRUPTS 0 +#endif + +#ifndef CONFIG_SGI +#define KBD_REPORT_ERR +#endif +#define KBD_REPORT_UNKN +/* #define KBD_IS_FOCUS_9000 */ + +int (*kbd_inb_p)(unsigned short port); +int (*kbd_inb)(unsigned short port); +void (*kbd_outb_p)(unsigned char data, unsigned short port); +void (*kbd_outb)(unsigned char data, unsigned short port); + +#ifdef CONFIG_MIPS_JAZZ +#define INIT_KBD /* full initialization for the keyboard controller. */ + +static volatile keyboard_hardware *jazz_kh; + +static int +jazz_kbd_inb_p(unsigned short port) +{ + int result; + + if(port == KBD_DATA_REG) + result = jazz_kh->data; + else /* Must be KBD_STATUS_REG */ + result = jazz_kh->command; + inb(0x80); + + return result; +} + +static int +jazz_kbd_inb(unsigned short port) +{ + int result; + + if(port == KBD_DATA_REG) + result = jazz_kh->data; + else /* Must be KBD_STATUS_REG */ + result = jazz_kh->command; + + return result; +} + +static void +jazz_kbd_outb_p(unsigned char data, unsigned short port) +{ + if(port == KBD_DATA_REG) + jazz_kh->data = data; + else if(port == KBD_CNTL_REG) + jazz_kh->command = data; + inb(0x80); +} + +static void +jazz_kbd_outb(unsigned char data, unsigned short port) +{ + if(port == KBD_DATA_REG) + jazz_kh->data = data; + else if(port == KBD_CNTL_REG) + jazz_kh->command = data; +} +#endif /* CONFIG_MIPS_JAZZ */ + +#ifdef CONFIG_SGI +#define INIT_KBD /* full initialization for the keyboard controller. */ + +static volatile struct hpc_keyb *sgi_kh; + +static int +sgi_kbd_inb(unsigned short port) +{ + int result; + + if(port == KBD_DATA_REG) + result = sgi_kh->data; + else /* Must be KBD_STATUS_REG */ + result = sgi_kh->command; + + return result; +} + +static void +sgi_kbd_outb(unsigned char data, unsigned short port) +{ + if(port == KBD_DATA_REG) + sgi_kh->data = data; + else if(port == KBD_CNTL_REG) + sgi_kh->command = data; +} +#endif /* CONFIG_SGI */ -#endif /* __KERNEL__ */ +/* + * Most other MIPS machines access the keyboard controller via + * ordinary I/O ports. + */ +static int +port_kbd_inb_p(unsigned short port) +{ + return inb_p(port); +} + +static int +port_kbd_inb(unsigned short port) +{ + return inb(port); +} + +static void +port_kbd_outb_p(unsigned char data, unsigned short port) +{ + return outb_p(data, port); +} + +static void +port_kbd_outb(unsigned char data, unsigned short port) +{ + return outb(data, port); +} + +extern __inline__ void keyboard_setup(void) +{ +#ifdef CONFIG_MIPS_JAZZ + if (mips_machgroup == MACH_GROUP_JAZZ) { + jazz_kh = (void *) JAZZ_KEYBOARD_ADDRESS; + kbd_inb_p = jazz_kbd_inb_p; + kbd_inb = jazz_kbd_inb; + kbd_outb_p = jazz_kbd_outb_p; + kbd_outb = jazz_kbd_outb; + /* + * Enable keyboard interrupts. + */ + *((volatile u16 *)JAZZ_IO_IRQ_ENABLE) |= JAZZ_IE_KEYBOARD; + set_cp0_status(IE_IRQ1, IE_IRQ1); + } else +#endif + if (mips_machgroup == MACH_GROUP_ARC || /* this is for Deskstation */ + (mips_machgroup == MACH_GROUP_SNI_RM + && mips_machtype == MACH_SNI_RM200_PCI)) { + /* + * These machines address their keyboard via the normal + * port address range. + * + * Also enable Scan Mode 2. + */ + kbd_inb_p = port_kbd_inb_p; + kbd_inb = port_kbd_inb; + kbd_outb_p = port_kbd_outb_p; + kbd_outb = port_kbd_outb; + request_region(0x60,16,"keyboard"); + } +#ifdef CONFIG_SGI + if (mips_machgroup == MACH_GROUP_SGI) { + sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); + kbd_inb_p = sgi_kbd_inb; + kbd_inb = sgi_kbd_inb; + kbd_outb_p = sgi_kbd_outb; + kbd_outb = sgi_kbd_outb; + } +#endif +} -#endif /* __ASMMIPS_KEYBOARD_H */ +#endif /* __KERNEL */ +#endif /* __ASM_MIPS_KEYBOARD_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h --- v2.1.43/linux/include/asm-mips/mc146818rtc.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/mc146818rtc.h Thu Jun 26 12:33:39 1997 @@ -9,7 +9,7 @@ #ifndef RTC_PORT #define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 1 +#define RTC_ALWAYS_BCD 0 /* RTC operates in binary mode */ #endif /* @@ -17,12 +17,10 @@ * 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(); \ +feature->rtc_read_data(addr); \ }) #define CMOS_WRITE(val, addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -feature->rtc_write_data(val); \ +feature->rtc_write_data(val, addr); \ }) #endif /* __ASM_MIPS_MC146818RTC_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsconfig.h linux/include/asm-mips/mipsconfig.h --- v2.1.43/linux/include/asm-mips/mipsconfig.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/mipsconfig.h Thu Jun 26 12:33:39 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994, 1995 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle */ #ifndef __ASM_MIPS_MIPSCONFIG_H #define __ASM_MIPS_MIPSCONFIG_H @@ -15,44 +15,16 @@ * Must be a value that can be load with a lui instruction. */ #ifndef PORT_BASE -#define PORT_BASE 0xe2000000 +#if !defined (__LANGUAGE_ASSEMBLY__) +extern unsigned long port_base; +#endif +#define PORT_BASE port_base #endif -/* - * Pagetables are 4MB mapped at 0xe4000000 - * Must be a value that can be loaded with a single instruction. - */ -#define TLBMAP 0xe4000000 - -/* - * The virtual address where we'll map the pagetables - * For a base address of 0xe3000000 this is 0xe338c000 - * For a base address of 0xe4000000 this is 0xe4390000 - * FIXME: Gas computes the following expression with signed - * shift and therefore false -#define TLB_ROOT (TLBMAP + (TLBMAP >> (12-2))) - */ -#define TLB_ROOT 0xe4390000 - -/* - * 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. Useful to find trouble with caches in drivers. - */ -#undef CONF_DISABLE_KSEG0_CACHING +/* Pgdir is 1 page mapped at 0xff800000. */ +#define TLBMAP 0xff800000 -/* - * Set this to one to enable additional vdma debug code. - */ -#define CONF_DEBUG_VDMA 0 +/* The virtual address where we'll map the pgdir. */ +#define TLB_ROOT 0xff000000 #endif /* __ASM_MIPS_MIPSCONFIG_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsprom.h linux/include/asm-mips/mipsprom.h --- v2.1.43/linux/include/asm-mips/mipsprom.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/mipsprom.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,74 @@ +#ifndef __ASM_MIPS_PROM_H +#define __ASM_MIPS_PROM_H + +#define PROM_RESET 0 +#define PROM_EXEC 1 +#define PROM_RESTART 2 +#define PROM_REINIT 3 +#define PROM_REBOOT 4 +#define PROM_AUTOBOOT 5 +#define PROM_OPEN 6 +#define PROM_READ 7 +#define PROM_WRITE 8 +#define PROM_IOCTL 9 +#define PROM_CLOSE 10 +#define PROM_GETCHAR 11 +#define PROM_PUTCHAR 12 +#define PROM_SHOWCHAR 13 /* XXX */ +#define PROM_GETS 14 /* XXX */ +#define PROM_PUTS 15 /* XXX */ +#define PROM_PRINTF 16 /* XXX */ + +/* What are these for? */ +#define PROM_INITPROTO 17 /* XXX */ +#define PROM_PROTOENABLE 18 /* XXX */ +#define PROM_PROTODISABLE 19 /* XXX */ +#define PROM_GETPKT 20 /* XXX */ +#define PROM_PUTPKT 21 /* XXX */ + +/* More PROM shit. Probably has to do with VME RMW cycles??? */ +#define PROM_ORW_RMW 22 /* XXX */ +#define PROM_ORH_RMW 23 /* XXX */ +#define PROM_ORB_RMW 24 /* XXX */ +#define PROM_ANDW_RMW 25 /* XXX */ +#define PROM_ANDH_RMW 26 /* XXX */ +#define PROM_ANDB_RMW 27 /* XXX */ + +/* Cache handling stuff */ +#define PROM_FLUSHCACHE 28 /* XXX */ +#define PROM_CLEARCACHE 29 /* XXX */ + +/* Libc alike stuff */ +#define PROM_SETJMP 30 /* XXX */ +#define PROM_LONGJMP 31 /* XXX */ +#define PROM_BEVUTLB 32 /* XXX */ +#define PROM_GETENV 33 /* XXX */ +#define PROM_SETENV 34 /* XXX */ +#define PROM_ATOB 35 /* XXX */ +#define PROM_STRCMP 36 /* XXX */ +#define PROM_STRLEN 37 /* XXX */ +#define PROM_STRCPY 38 /* XXX */ +#define PROM_STRCAT 39 /* XXX */ + +/* Misc stuff */ +#define PROM_PARSER 40 /* XXX */ +#define PROM_RANGE 41 /* XXX */ +#define PROM_ARGVIZE 42 /* XXX */ +#define PROM_HELP 43 /* XXX */ + +/* Entry points for some PROM commands */ +#define PROM_DUMPCMD 44 /* XXX */ +#define PROM_SETENVCMD 45 /* XXX */ +#define PROM_UNSETENVCMD 46 /* XXX */ +#define PROM_PRINTENVCMD 47 /* XXX */ +#define PROM_BEVEXCEPT 48 /* XXX */ +#define PROM_ENABLECMD 49 /* XXX */ +#define PROM_DISABLECMD 50 /* XXX */ + +#define PROM_CLEARNOFAULT 51 /* XXX */ +#define PROM_NOTIMPLEMENT 52 /* XXX */ + +#define PROM_NV_GET 53 /* XXX */ +#define PROM_NV_SET 54 /* XXX */ + +#endif /* __ASM_MIPS_PROM_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h --- v2.1.43/linux/include/asm-mips/mipsregs.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/mipsregs.h Thu Jun 26 12:33:40 1997 @@ -5,17 +5,18 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994, 1995 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + * Modified for further R[236]000 support by Paul M. Antoine, 1996. */ - #ifndef __ASM_MIPS_MIPSREGS_H #define __ASM_MIPS_MIPSREGS_H +#include + /* * The following macros are especially useful for __asm__ * inline assembler. */ - #ifndef __STR #define __STR(x) #x #endif @@ -24,17 +25,6 @@ #endif /* - * On the R2000/3000 load instructions are not interlocked - - * we therefore sometimes need to fill load delay slots with a nop - * which would be useless for ISA >= 2. - */ -#if !defined (__R4000__) -#define FILL_LDS nop -#else -#define FILL_LDS -#endif - -/* * Coprocessor 0 register names */ #define CP0_INDEX $0 @@ -67,6 +57,20 @@ #define CP0_ERROREPC $30 /* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* * Coprocessor 1 (FPU) register names */ #define CP1_REVISION $0 @@ -104,6 +108,9 @@ : "=r" (__res)); \ __res;}) +/* + * For now use this only with interrupts disabled! + */ #define read_64bit_cp0_register(source) \ ({ int __res; \ __asm__ __volatile__( \ @@ -176,9 +183,14 @@ /* * Inline code for use of the ll and sc instructions * - * FIXME: This instruction is only available on MIPS ISA >=3. + * FIXME: This instruction is only available on MIPS ISA >=2. * Since these operations are only being used for atomic operations * the easiest workaround for the R[23]00 is to disable interrupts. + * This fails for R3000 SMP machines which use that many different + * technologies as replacement that it is difficult to create even + * just a hook for for all machines to hook into. The only good + * thing is that there is currently no R3000 SMP machine on the + * Linux/MIPS target list ... */ #define load_linked(addr) \ ({ \ @@ -187,7 +199,7 @@ __asm__ __volatile__( \ "ll\t%0,(%1)" \ : "=r" (__res) \ - : "r" ((unsigned int) (addr))); \ + : "r" ((unsigned long) (addr))); \ \ __res; \ }) @@ -205,35 +217,53 @@ }) /* - * Bitfields in the cp0 status register - * - * Refer to the MIPS R4xx0 manuals, chapter 5 for explanation. - * FIXME: This doesn't cover all R4xx0 processors. + * Bitfields in the R4xx0 cp0 status register */ -#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 */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_KUC 0x00000001 +#define ST0_IEP 0x00000002 +#define ST0_KUP 0x00000004 +#define ST0_IEO 0x00000008 +#define ST0_KUO 0x00000010 +/* bits 6 & 7 are reserved on R[23]000 */ + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM <1 << 4) +#define ST0_IL (1 << 23) +#define ST0_DL (1 << 24) + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ /* * Bitfields and bit numbers in the coprocessor 0 cause register. @@ -264,5 +294,78 @@ #define CAUSEF_CE (3 << 28) #define CAUSEB_BD 31 #define CAUSEF_BD (1 << 31) + +/* + * Bits in the coprozessor 0 config register. + */ +#define CONFIG_DB (1 << 4) +#define CONFIG_IB (1 << 5) +#define CONFIG_SC (1 << 17) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + * time accounting with a precission of one cycle. I don't have + * R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES 0 +#define CE0_INSN_ISSUED 1 +#define CE0_LPSC_ISSUED 2 +#define CE0_S_ISSUED 3 +#define CE0_SC_ISSUED 4 +#define CE0_SC_FAILED 5 +#define CE0_BRANCH_DECODED 6 +#define CE0_QW_WB_SECONDARY 7 +#define CE0_CORRECTED_ECC_ERRORS 8 +#define CE0_ICACHE_MISSES 9 +#define CE0_SCACHE_I_MISSES 10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 +#define CE0_EXT_INTERVENTIONS_REQ 12 +#define CE0_EXT_INVALIDATE_REQ 13 +#define CE0_VIRTUAL_COHERENCY_COND 14 +#define CE0_INSN_GRADUATED 15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES 0 +#define CE1_INSN_GRADUATED 1 +#define CE1_LPSC_GRADUATED 2 +#define CE1_S_GRADUATED 3 +#define CE1_SC_GRADUATED 4 +#define CE1_FP_INSN_GRADUATED 5 +#define CE1_QW_WB_PRIMARY 6 +#define CE1_TLB_REFILL 7 +#define CE1_BRANCH_MISSPREDICTED 8 +#define CE1_DCACHE_MISS 9 +#define CE1_SCACHE_D_MISSES 10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 +#define CE1_EXT_INTERVENTION_HITS 12 +#define CE1_EXT_INVALIDATE_REQ 13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 + +/* + * These flags define in which priviledge mode the counters count events + */ +#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + +#ifndef __LANGUAGE_ASSEMBLY__ +/* + * Functions to access the performance counter and control registers + */ +extern asmlinkage unsigned int read_perf_cntr(unsigned int counter); +extern asmlinkage void write_perf_cntr(unsigned int counter, unsigned int val); +extern asmlinkage unsigned int read_perf_cntl(unsigned int counter); +extern asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val); +#endif #endif /* __ASM_MIPS_MIPSREGS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mman.h linux/include/asm-mips/mman.h --- v2.1.43/linux/include/asm-mips/mman.h Sun Oct 6 22:55:48 1996 +++ linux/include/asm-mips/mman.h Thu Jun 26 12:33:40 1997 @@ -36,6 +36,7 @@ #define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand */ /* These are linux-specific */ +#define MAP_NORESERVE 0x0400 /* don't check for reservations */ #define MAP_ANONYMOUS 0x0800 /* don't use a file */ #define MAP_GROWSDOWN 0x1000 /* stack-like segment */ #define MAP_DENYWRITE 0x2000 /* ETXTBSY */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h --- v2.1.43/linux/include/asm-mips/mmu_context.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/mmu_context.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,65 @@ +/* + * Switch a MMU context. + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MMU_CONTEXT_H +#define __ASM_MIPS_MMU_CONTEXT_H + +#define MAX_ASID 255 + +extern unsigned long asid_cache; + +#define ASID_VERSION_SHIFT 16 +#define ASID_VERSION_MASK ((~0UL) << ASID_VERSION_SHIFT) +#define ASID_FIRST_VERSION (1UL << ASID_VERSION_SHIFT) + +extern inline void get_new_mmu_context(struct mm_struct *mm, unsigned long asid) +{ + /* check if it's legal.. */ + if ((asid & ~ASID_VERSION_MASK) > MAX_ASID) { + /* start a new version, invalidate all old asid's */ + flush_tlb_all(); + asid = (asid & ASID_VERSION_MASK) + ASID_FIRST_VERSION; + if (!asid) + asid = ASID_FIRST_VERSION; + } + asid_cache = asid + 1; + mm->context = asid; /* full version + asid */ +} + +extern inline void get_mmu_context(struct task_struct *p) +{ + struct mm_struct *mm = p->mm; + + if (mm) { + unsigned long asid = asid_cache; + /* Check if our ASID is of an older version and thus invalid */ + if ((mm->context ^ asid) & ASID_VERSION_MASK) + get_new_mmu_context(mm, asid); + } +} + +/* + * Initialize the context related info for a new mm_struct + * instance. + */ +extern inline void init_new_context(struct mm_struct *mm) +{ + mm->context = 0; +} + +/* + * Destroy context related info for an mm_struct that is about + * to be put to rest. + */ +extern inline void destroy_context(struct mm_struct *mm) +{ + mm->context = 0; +} + +#endif /* __ASM_MIPS_MMU_CONTEXT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h --- v2.1.43/linux/include/asm-mips/namei.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/namei.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,54 @@ +/* + * linux/include/asm-mips/namei.h + * + * Included from linux/fs/namei.c + */ +#ifndef __ASM_MIPS_NAMEI_H +#define __ASM_MIPS_NAMEI_H + +#include + +#ifdef CONFIG_BINFMT_IRIX + +/* Only one at this time. */ +#define IRIX32_EMUL "usr/gnemul/irix/" + +extern int __namei(int, const char *, struct inode *, char *, struct inode **, + struct inode **, struct qstr *, struct dentry **, int *); + +static __inline__ int +__prefix_namei(int retrieve_mode, const char * name, struct inode * base, + char * buf, struct inode ** res_dir, struct inode ** res_inode, + struct qstr * last_name, struct dentry ** last_entry, + int * last_error) +{ + int error; + + if (current->personality != PER_IRIX32) + return -EINVAL; + + while (*name == '/') + name++; + + atomic_inc(¤t->fs->root->i_count); + error = __namei(NAM_FOLLOW_LINK, IRIX32_EMUL, current->fs->root, + buf, NULL, &base, NULL, NULL, NULL); + if (error) + return error; + + error = __namei(retrieve_mode, name, base, buf, res_dir, res_inode, + last_name, last_entry, last_error); + if (error) + return error; + + return 0; +} + +#else /* !defined(CONFIG_BINFMT_IRIX) */ + +#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \ + last_name, last_entry, last_error) 1 + +#endif /* !defined(CONFIG_BINFMT_IRIX) */ + +#endif /* __ASM_MIPS_NAMEI_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/offset.h linux/include/asm-mips/offset.h --- v2.1.43/linux/include/asm-mips/offset.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/offset.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,88 @@ +/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */ + +#ifndef _MIPS_OFFSET_H +#define _MIPS_OFFSET_H + +/* MIPS pt_regs offsets. */ +#define PT_R0 24 +#define PT_R1 28 +#define PT_R2 32 +#define PT_R3 36 +#define PT_R4 40 +#define PT_R5 44 +#define PT_R6 48 +#define PT_R7 52 +#define PT_R8 56 +#define PT_R9 60 +#define PT_R10 64 +#define PT_R11 68 +#define PT_R12 72 +#define PT_R13 76 +#define PT_R14 80 +#define PT_R15 84 +#define PT_R16 88 +#define PT_R17 92 +#define PT_R18 96 +#define PT_R19 100 +#define PT_R20 104 +#define PT_R21 108 +#define PT_R22 112 +#define PT_R23 116 +#define PT_R24 120 +#define PT_R25 124 +#define PT_R26 128 +#define PT_R27 132 +#define PT_R28 136 +#define PT_R29 140 +#define PT_R30 144 +#define PT_R31 148 +#define PT_LO 152 +#define PT_HI 156 +#define PT_OR2 160 +#define PT_OR7 164 +#define PT_EPC 168 +#define PT_BVADDR 172 +#define PT_STATUS 176 +#define PT_CAUSE 180 +#define PT_SIZE 184 + +/* MIPS task_struct offsets. */ +#define TASK_STATE 0 +#define TASK_COUNTER 4 +#define TASK_PRIORITY 8 +#define TASK_SIGNAL 12 +#define TASK_BLOCKED 16 +#define TASK_FLAGS 20 +#define TASK_MM 912 + +/* MIPS specific thread_struct offsets. */ +#define THREAD_REG16 544 +#define THREAD_REG17 548 +#define THREAD_REG18 552 +#define THREAD_REG19 556 +#define THREAD_REG20 560 +#define THREAD_REG21 564 +#define THREAD_REG22 568 +#define THREAD_REG23 572 +#define THREAD_REG28 576 +#define THREAD_REG29 580 +#define THREAD_REG30 584 +#define THREAD_REG31 588 +#define THREAD_STATUS 592 +#define THREAD_FPU 600 +#define THREAD_BVADDR 864 +#define THREAD_ECODE 868 +#define THREAD_TRAPNO 872 +#define THREAD_KSP 876 +#define THREAD_PGDIR 880 +#define THREAD_MFLAGS 884 +#define THREAD_CURDS 888 +#define THREAD_TRAMP 892 +#define THREAD_OLDCTX 896 + +/* Linux mm_struct offsets. */ +#define MM_COUNT 12 +#define MM_PGD 8 +#define MM_CONTEXT 28 + +#endif /* !(_MIPS_OFFSET_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/page.h linux/include/asm-mips/page.h --- v2.1.43/linux/include/asm-mips/page.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/page.h Thu Jun 26 12:33:40 1997 @@ -1,3 +1,12 @@ +/* + * Definitions for page handling + * + * 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, 1996 by Ralf Baechle + */ #ifndef __ASM_MIPS_PAGE_H #define __ASM_MIPS_PAGE_H @@ -12,6 +21,9 @@ #ifndef __LANGUAGE_ASSEMBLY__ +extern void (*clear_page)(unsigned long page); +extern void (*copy_page)(unsigned long to, unsigned long from); + #ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. @@ -52,51 +64,21 @@ #endif /* !defined (STRICT_MM_TYPECHECKS) */ -/* - * 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 void __copy_page(unsigned long from, unsigned long to); -#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to) - #endif /* __LANGUAGE_ASSEMBLY__ */ /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -/* This handles the memory map */ -#if __mips == 3 /* - * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent) - * Pagetables are at XKPHYS + 0x1000000000000000 (uncached) + * This handles the memory map. + * We handle pages at KSEG0 for kernels with 32 bit address space. */ -#define PAGE_OFFSET 0x9800000000000000UL -#define PT_OFFSET 0x9000000000000000UL -#define MAP_MASK 0x07ffffffffffffffUL -#else -/* - * We handle pages at KSEG0 (cachable, noncoherent) - * Pagetables are at KSEG1 (uncached) - */ -#define PAGE_OFFSET 0x80000000 -#define PT_OFFSET 0xa0000000 -#define MAP_MASK 0x1fffffff -#endif - +#define PAGE_OFFSET 0x80000000UL +#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#define MAP_MASK 0x1fffffffUL #define MAP_NR(addr) ((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT) -#ifndef __LANGUAGE_ASSEMBLY__ - -extern unsigned long page_colour_mask; - -extern inline unsigned long -page_colour(unsigned long page) -{ - return page & page_colour_mask; -} - -#endif /* defined (__LANGUAGE_ASSEMBLY__) */ #endif /* defined (__KERNEL__) */ #endif /* __ASM_MIPS_PAGE_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h --- v2.1.43/linux/include/asm-mips/pci.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/pci.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,39 @@ +/* + * 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. + * + * Declarations for the MIPS specific implementation of the PCI BIOS32 services. + */ +#ifndef __ASM_MIPS_PCI_H +#define __ASM_MIPS_PCI_H + +extern unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end); +extern unsigned long (*_pcibios_fixup) (unsigned long memory_start, + unsigned long memory_end); +extern int (*_pcibios_read_config_byte) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char *val); +extern int (*_pcibios_read_config_word) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short *val); +extern int (*_pcibios_read_config_dword) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int *val); +extern int (*_pcibios_write_config_byte) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char val); +extern int (*_pcibios_write_config_word) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short val); +extern int (*_pcibios_write_config_dword) (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int val); + +#endif /* __ASM_MIPS_PCI_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v2.1.43/linux/include/asm-mips/pgtable.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/pgtable.h Thu Jun 26 12:33:40 1997 @@ -1,63 +1,49 @@ #ifndef __ASM_MIPS_PGTABLE_H #define __ASM_MIPS_PGTABLE_H +#include +#include + #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. +/* Cache flushing: * - * 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. - */ + * - flush_cache_all() flushes entire cache + * - flush_cache_mm(mm) flushes the specified mm context's cache lines + * - flush_cache_page(mm, vmaddr) flushes a single page + * - flush_cache_range(mm, start, end) flushes a range of pages + * - flush_page_to_ram(page) write back kernel page to ram + */ +extern void (*flush_cache_all)(void); +extern void (*flush_cache_mm)(struct mm_struct *mm); +extern void (*flush_cache_range)(struct mm_struct *mm, unsigned long start, + unsigned long end); +extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); +extern void (*flush_cache_sigtramp)(unsigned long addr); +extern void (*flush_page_to_ram)(unsigned long page); -/* - * 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 +/* TLB flushing: * - * 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. + * - flush_tlb_all() flushes all processes TLB entries + * - flush_tlb_mm(mm) flushes the specified mm context TLB entries + * - flush_tlb_page(mm, vmaddr) flushes a single page + * - flush_tlb_range(mm, start, end) flushes a range of pages + */ +extern void (*flush_tlb_all)(void); +extern void (*flush_tlb_mm)(struct mm_struct *mm); +extern void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start, + unsigned long end); +extern void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); + +/* Basically we have the same two-level (which is the logical three level + * Linux page table layout folded) page tables as the i386. Some day + * when we have proper page coloring support we can have a 1% quicker + * tlb refill handling mechanism, but for now it is a bit slower but + * works even with the cache aliasing problem the R4k and above have. */ -#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ @@ -71,8 +57,7 @@ #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) -/* - * entries per page directory level: we use two-level, so +/* Entries per page directory level: we use two-level, so * we don't really have any PMD directory physically. */ #define PTRS_PER_PTE 1024 @@ -82,22 +67,32 @@ #define VMALLOC_START KSEG2 #define VMALLOC_VMADDR(x) ((unsigned long)(x)) -/* - * Note that we shift the lower 32bits of each EntryLo[01] entry +/* 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 chosen some quite misleading names for the - * valid and dirty bits they're defined here but only their synonyms - * will be used. + * + * Similar to the Alpha port, we need to keep track of the ref + * and mod bits in software. We have a software "yeah you can read + * from this page" bit, and a hardware one which actually lets the + * process read from the page. On the same token we have a software + * writable bit and the real hardware one which actually lets the + * process write to the page, this keeps a mod bit via the hardware + * dirty bit. + * + * Certain revisions of the R4000 and R5000 have a bug where if a + * certain sequence occurs in the last 3 instructions of an executable + * page, and the following page is not mapped, the cpu can do + * unpredictable things. The code (when it is written) to deal with + * this problem will be in the update_mmu_cache() code for the r4k. */ #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_READ (1<<1) /* implemented in software */ +#define _PAGE_WRITE (1<<2) /* implemented in software */ +#define _PAGE_ACCESSED (1<<3) /* implemented in software */ +#define _PAGE_MODIFIED (1<<4) /* implemented in software */ +#define _PAGE_R4KBUG (1<<5) /* workaround for r4k bug */ #define _PAGE_GLOBAL (1<<6) #define _PAGE_VALID (1<<7) #define _PAGE_SILENT_READ (1<<7) /* synonym */ @@ -116,16 +111,15 @@ #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_CHG_MASK (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK) -#define PAGE_NONE __pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \ +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | __READABLE | \ +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _CACHE_CACHABLE_NONCOHERENT) @@ -155,9 +149,6 @@ #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. @@ -166,13 +157,15 @@ * for zero-mapped memory areas etc.. */ extern pte_t __bad_page(void); -extern pte_t * __bad_pagetable(void); +extern pte_t *__bad_pagetable(void); extern unsigned long __zero_page(void); +extern unsigned long empty_zero_page[1024]; + #define BAD_PAGETABLE __bad_pagetable() #define BAD_PAGE __bad_page() -#define ZERO_PAGE __zero_page() +#define ZERO_PAGE ((unsigned long)empty_zero_page) /* number of bits that fit into a memory pointer */ #define BITS_PER_PTR (8*sizeof(unsigned long)) @@ -181,31 +174,19 @@ #define PTR_MASK (~(sizeof(void*)-1)) /* - * sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) +extern void (*load_pgd)(unsigned long pg_dir); + /* 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) +#define SET_PAGE_DIR(tsk,pgdir) (tsk)->tss.pg_dir = ((unsigned long) (pgdir)) -extern unsigned long high_memory; extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)]; /* @@ -213,39 +194,60 @@ * 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); } +{ + 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); } +{ + return pmd_val(pmd); +} extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) -{ pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); } +{ + pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK); +} + +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_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) +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +extern inline void set_pte(pte_t *ptep, pte_t pteval) { - if (!mem_map[MAP_NR(ptep)].reserved) - mem_map[MAP_NR(ptep)].count++; + *ptep = pteval; +} + +extern inline void pte_clear(pte_t *ptep) +{ + set_pte(ptep, __pte(0)); } /* * 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_none(pmd_t pmd) +{ + return pmd_val(pmd) == ((unsigned long) invalid_pte_table); +} 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) { } + return ((pmd_page(pmd) > (unsigned long) high_memory) || + (pmd_page(pmd) < PAGE_OFFSET)); +} + +extern inline int pmd_present(pmd_t pmd) +{ + return pmd_val(pmd); +} + +extern inline void pmd_clear(pmd_t *pmdp) +{ + pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); +} /* * The "pgd_xxx()" functions here are trivial for a folded two-level @@ -255,36 +257,41 @@ 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) { } +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 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_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 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; + pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); + return pte; } -extern inline pte_t pte_exprotect(pte_t pte) + +extern inline pte_t pte_mkclean(pte_t pte) { - pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte; + pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); + 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_mkold(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); + return pte; +} + extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; @@ -292,6 +299,7 @@ pte_val(pte) |= _PAGE_SILENT_WRITE; return pte; } + extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; @@ -299,13 +307,7 @@ 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; @@ -313,257 +315,453 @@ 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) - { + if (pte_val(pte) & _PAGE_READ) { pte_val(pte) |= _PAGE_SILENT_READ; - if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == (_PAGE_WRITE|_PAGE_MODIFIED)) + 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; } +{ + return __pte(((page & PAGE_MASK) - PAGE_OFFSET) | pgprot_val(pgprot)); +} + +extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) +{ + return __pte((physpage - PAGE_OFFSET) | pgprot_val(pgprot)); +} 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; } +{ + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); +} + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) /* to find an entry in a page-table-directory */ -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +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) +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) +extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address) { - return (pte_t *) (pmd_page(*dir) + (PT_OFFSET - PAGE_OFFSET)) + + return (pte_t *) (pmd_page(*dir)) + ((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. + * if any. */ -extern inline void pte_free_kernel(pte_t * pte) +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); + free_page((unsigned long) pte); } -extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +extern const char bad_pmd_string[]; + +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); + pte_t *page = (pte_t *) 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, page); + return page + address; } pmd_set(pmd, (pte_t *) BAD_PAGETABLE); return NULL; } - free_page(page); + free_page((unsigned long) page); } if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd)); + printk(bad_pmd_string, pmd_val(*pmd)); pmd_set(pmd, (pte_t *) BAD_PAGETABLE); return NULL; } - return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address; + return (pte_t *) pmd_page(*pmd) + 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 void pmd_free_kernel(pmd_t *pmd) { + pmd_val(*pmd) = ((unsigned long) invalid_pte_table); } -extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) +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) +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); + free_page((unsigned long) pte); } -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +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); + pte_t *page = (pte_t *) 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, page); + return page + address; } pmd_set(pmd, (pte_t *) BAD_PAGETABLE); return NULL; } - free_page(page); + free_page((unsigned long) page); } if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + printk(bad_pmd_string, pmd_val(*pmd)); pmd_set(pmd, (pte_t *) BAD_PAGETABLE); return NULL; } - return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address; + return (pte_t *) pmd_page(*pmd) + 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 void pmd_free(pmd_t *pmd) { + pmd_val(*pmd) = ((unsigned long) invalid_pte_table); } -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) +extern inline pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address) { return (pmd_t *) pgd; } -extern inline void pgd_free(pgd_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); + free_page((unsigned long) pgd); } /* * 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 void (*pgd_init)(unsigned long page); -extern inline pgd_t * pgd_alloc(void) +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)); + return (pgd_t *) page; } extern pgd_t swapper_pg_dir[1024]; +extern void (*update_mmu_cache)(struct vm_area_struct *vma, + unsigned long address, pte_t pte); + /* - * 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 unnecessary - * exceptions. + * Kernel with 32 bit address space */ -extern void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte); +#define SWP_TYPE(entry) (((entry) >> 8) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 15) +#define SWP_ENTRY(type,offset) (((type) << 8) | ((offset) << 15)) -#if __mips >= 3 +/* TLB operations. */ +extern inline void tlb_probe(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbp\n\t" + ".set reorder"); +} -#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))) +extern inline void tlb_read(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbr\n\t" + ".set reorder"); +} -#else +extern inline void tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwi\n\t" + ".set reorder"); +} + +extern inline void tlb_write_random(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwr\n\t" + ".set reorder"); +} + +/* Dealing with various CP0 mmu/cache related registers. */ + +/* CP0_PAGEMASK register */ +extern inline unsigned long get_pagemask(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $5\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + return val; +} + +extern inline void set_pagemask(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $5\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +/* CP0_ENTRYLO0 and CP0_ENTRYLO1 registers */ +extern inline unsigned long get_entrylo0(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $2\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + return val; +} -#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) -#define SWP_OFFSET(entry) ((entry) >> 8) -#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) +extern inline void set_entrylo0(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $2\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +extern inline unsigned long get_entrylo1(void) +{ + unsigned long val; -#endif + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $3\n\t" + ".set mips2\n\t" + ".set reorder" : "=r" (val)); + + return val; +} + +extern inline void set_entrylo1(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $3\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +/* CP0_ENTRYHI register */ +extern inline unsigned long get_entryhi(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $10\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + + return val; +} + +extern inline void set_entryhi(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $10\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +/* CP0_INDEX register */ +extern inline unsigned long get_index(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $0\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + return val; +} + +extern inline void set_index(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $0\n\t" + ".set mips2\n\t" + ".set reorder\n\t" + : : "r" (val)); +} + +/* CP0_WIRED register */ +extern inline unsigned long get_wired(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $6\n\t" + ".set mips2\n\t" + ".set reorder\n\t" + : "=r" (val)); + return val; +} + +extern inline void set_wired(unsigned long val) +{ + __asm__ __volatile__( + "\n\t.set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $6\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +/* CP0_TAGLO and CP0_TAGHI registers */ +extern inline unsigned long get_taglo(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $28\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + return val; +} + +extern inline void set_taglo(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $28\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +extern inline unsigned long get_taghi(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $29\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + return val; +} + +extern inline void set_taghi(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $29\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} + +/* CP0_CONTEXT register */ +extern inline unsigned long get_context(void) +{ + unsigned long val; + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mfc0 %0, $4\n\t" + ".set mips2\n\t" + ".set reorder" + : "=r" (val)); + + return val; +} + +extern inline void set_context(unsigned long val) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "mtc0 %0, $4\n\t" + ".set mips2\n\t" + ".set reorder" + : : "r" (val)); +} #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/poll.h linux/include/asm-mips/poll.h --- v2.1.43/linux/include/asm-mips/poll.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/poll.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,26 @@ +#ifndef __ASM_MIPS_POLL_H +#define __ASM_MIPS_POLL_H + +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 + +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +#define POLLRDNORM 0x0040 +#define POLLRDBAND 0x0080 +#define POLLWRNORM POLLOUT +#define POLLWRBAND 0x0100 + +/* XXX This one seems to be more-or-less nonstandard. */ +#define POLLMSG 0x0400 + +struct pollfd { + int fd; + short events; + short revents; +}; + +#endif /* __ASM_MIPS_POLL_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/posix_types.h linux/include/asm-mips/posix_types.h --- v2.1.43/linux/include/asm-mips/posix_types.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/posix_types.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,117 @@ +/* + * POSIX types + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ARCH_MIPS_POSIX_TYPES_H +#define __ARCH_MIPS_POSIX_TYPES_H + +#define __need_size_t +#define __need_ptrdiff_t +#include + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned long __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long __kernel_pid_t; +typedef long __kernel_ipc_pid_t; +typedef long __kernel_uid_t; +typedef long __kernel_gid_t; +typedef __SIZE_TYPE__ __kernel_size_t; +typedef __SSIZE_TYPE__ __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; +/* typedef unsigned long __kernel_sigset_t; anybody using this type? */ + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { + long val[2]; +} __kernel_fsid_t; + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long __fd, __kernel_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, __kernel_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, const __kernel_fd_set *__p) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *__p) +{ + unsigned long *__tmp = __p->fds_bits; + int __i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + __tmp[ 4] = 0; __tmp[ 5] = 0; + __tmp[ 6] = 0; __tmp[ 7] = 0; + __tmp[ 8] = 0; __tmp[ 9] = 0; + __tmp[10] = 0; __tmp[11] = 0; + __tmp[12] = 0; __tmp[13] = 0; + __tmp[14] = 0; __tmp[15] = 0; + return; + + 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; + + case 4: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + return; + } + } + __i = __FDSET_LONGS; + while (__i) { + __i--; + *__tmp = 0; + __tmp++; + } +} + +#endif /* __ARCH_MIPS_POSIX_TYPES_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v2.1.43/linux/include/asm-mips/processor.h Tue May 13 22:41:17 1997 +++ linux/include/asm-mips/processor.h Thu Jun 26 12:33:40 1997 @@ -3,8 +3,8 @@ * * Copyright (C) 1994 Waldorf Electronics * written by Ralf Baechle + * Modified further for R[236]000 compatibility by Paul M. Antoine */ - #ifndef __ASM_MIPS_PROCESSOR_H #define __ASM_MIPS_PROCESSOR_H @@ -19,9 +19,6 @@ */ extern char wait_available; /* only available on R4[26]00 */ -extern atomic_t intr_count; -extern unsigned long event; - /* * Bus types (default is ISA, but people can check others with these..) * MCA_bus hardcoded to 0 for now. @@ -41,7 +38,9 @@ /* * User space process size: 2GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. + * so don't change it unless you know what you are doing. TASK_SIZE + * for a 64 bit kernel expandable to 8192EB, of which the current MIPS + * implementations will "only" be able to use 1TB ... */ #define TASK_SIZE (0x80000000UL) @@ -67,7 +66,7 @@ */ struct mips_fpu_soft_struct { long dummy; - }; +}; union mips_fpu_union { struct mips_fpu_hard_struct hard; @@ -82,62 +81,33 @@ * If you change thread_struct remember to change the #defines below too! */ struct thread_struct { - /* - * saved main processor registers - */ - unsigned long reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23; - unsigned long reg28, reg29, reg30, reg31; - /* - * saved cp0 stuff - */ + /* Saved main processor registers. */ + unsigned long reg16 __attribute__ ((aligned (8))); + unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; + unsigned long reg28, reg29, reg30, reg31; + + /* Saved cp0 stuff. */ unsigned long cp0_status; - /* - * saved fpu/fpu emulator stuff - */ - union mips_fpu_union fpu; - /* - * Other stuff associated with the thread - */ + + /* Saved fpu/fpu emulator stuff. */ + union mips_fpu_union fpu __attribute__ ((aligned (8))); + + /* 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 pg_dir; /* L1 page table pointer */ -#define MF_FIXADE 1 + unsigned long ksp; /* Top of kernel stack */ + unsigned long pg_dir; /* used in tlb refill */ +#define MF_FIXADE 1 /* Fix address errors in software */ +#define MF_LOGADE 2 /* Log address errors to syslog */ unsigned long mflags; + int current_ds; + unsigned long irix_trampoline; /* Wheee... */ + unsigned long irix_oldctx; }; #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ -/* - * If you change the #defines remember to change thread_struct above too! - */ -#define TOFF_REG16 0 -#define TOFF_REG17 (TOFF_REG16+4) -#define TOFF_REG18 (TOFF_REG17+4) -#define TOFF_REG19 (TOFF_REG18+4) -#define TOFF_REG20 (TOFF_REG19+4) -#define TOFF_REG21 (TOFF_REG20+4) -#define TOFF_REG22 (TOFF_REG21+4) -#define TOFF_REG23 (TOFF_REG22+4) -#define TOFF_REG28 (TOFF_REG23+4) -#define TOFF_REG29 (TOFF_REG28+4) -#define TOFF_REG30 (TOFF_REG29+4) -#define TOFF_REG31 (TOFF_REG30+4) -#define TOFF_CP0_STATUS (TOFF_REG31+4) -/* - * Pad for 8 byte boundary! - */ -#define TOFF_FPU (((TOFF_CP0_STATUS+4)+(8-1))&~(8-1)) -#define TOFF_CP0_BADVADDR (TOFF_FPU+264) -#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_PG_DIR (TOFF_KSP+4) -#define TOFF_MFLAGS (TOFF_PG_DIR+4) - -#if !defined (__LANGUAGE_ASSEMBLY__) - #define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \ VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } @@ -156,81 +126,79 @@ */ \ INIT_FPU, \ /* \ - * Other stuff associated with the process\ + * Other stuff associated with the process \ + */ \ + 0, 0, 0, (unsigned long)&init_task_union + KERNEL_STACK_SIZE - 8, \ + (unsigned long) swapper_pg_dir, \ + /* \ + * For now the default is to fix address errors \ */ \ - 0, 0, 0, sizeof(init_kernel_stack) + (unsigned long)init_kernel_stack - 8, \ - (unsigned long) swapper_pg_dir - PT_OFFSET, 0 \ + MF_FIXADE, 0, 0, 0 \ } +#ifdef __KERNEL__ + +#define KERNEL_STACK_SIZE 8192 + +#if !defined (__LANGUAGE_ASSEMBLY__) + +/* Free all resources held by a thread. */ +extern void release_thread(struct task_struct *); + /* * 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]; + return ((struct pt_regs *)(long)t->reg29)->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 loses kernel privileges. - */ - 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; -} - -/* Free all resources held by a thread. */ -extern void release_thread(struct task_struct *); - -#ifdef __KERNEL__ - -/* - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ -asmlinkage void resume(struct task_struct *tsk, int offset); - -#define switch_to(n) \ - resume(n, ((int)(&((struct task_struct *)0)->tss))) +extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); /* * Does the process account for user or for system time? */ -#if defined (__R4000__) - #define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x18)) -#else /* !defined (__R4000__) */ - -#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x4)) - -#endif /* !defined (__R4000__) */ +/* Allocation and freeing of basic task resources. */ +/* + * NOTE! The task struct and the stack go together + */ +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) -#endif /* __KERNEL__ */ +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ +#endif /* __KERNEL__ */ /* - * ELF support - * - * Using EM_MIPS is actually wrong - this one is reserved for big endian - * machines only + * Return_address is a replacement for __builtin_return_address(count) + * which on certain architectures cannot reasonably be implemented in GCC + * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * Note that __builtin_return_address(x>=1) is forbidden because GCC + * aborts compilation on some CPUs. It's simply not possible to unwind + * some CPU's stackframes. + */ +#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) +/* + * __builtin_return_address works only for non-leaf functions. We avoid the + * overhead of a function call by forcing the compiler to save the return + * address register on the stack. + */ +#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) +#else +/* + * __builtin_return_address is not implemented at all. Calling it + * will return senseless values. Return NULL which at least is an obviously + * senseless value. */ -#define INCOMPATIBLE_MACHINE(m) ((m) != EM_MIPS && (m) != EM_MIPS_RS4_BE) -#define ELF_EM_CPU EM_MIPS +#define return_address() NULL +#endif #endif /* __ASM_MIPS_PROCESSOR_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h --- v2.1.43/linux/include/asm-mips/ptrace.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/ptrace.h Thu Jun 26 12:33:40 1997 @@ -5,8 +5,7 @@ * 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 + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle * * Machine dependent structs and defines to help the user use * the ptrace system call. @@ -14,63 +13,52 @@ #ifndef __ASM_MIPS_PTRACE_H #define __ASM_MIPS_PTRACE_H +#include + +#ifndef __ASSEMBLY__ /* * 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[5]; + /* Pad bytes for argument save space on the stack. */ + unsigned long pad0[6]; - /* - * saved main processor registers - */ - long 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, reg28, reg29, reg30, reg31; + /* Saved main processor registers. */ + unsigned long regs[32]; - /* - * Saved special registers - */ - long lo; - long hi; + /* Other saved registers. */ + unsigned long lo; + unsigned long hi; + unsigned long orig_reg2; + unsigned long orig_reg7; /* * saved cp0 registers */ - unsigned long cp0_status; unsigned long cp0_epc; + unsigned long cp0_badvaddr; + unsigned long cp0_status; unsigned long cp0_cause; - - /* - * Some goodies... - */ - unsigned long interrupt; - long orig_reg2; - long pad1; }; +#endif /* !(__ASSEMBLY__) */ + +#include + #ifdef __KERNEL__ +#ifndef __ASSEMBLY__ /* * Does the process account for user or for system time? */ -#if defined (__R4000__) - #define user_mode(regs) ((regs)->cp0_status & 0x10) -#else /* !defined (__R4000__) */ - -#define user_mode(regs) (!((regs)->cp0_status & 0x8)) +#define instruction_pointer(regs) ((regs)->cp0_epc) -#endif /* !defined (__R4000__) */ +extern void (*show_regs)(struct pt_regs *); +#endif /* !(__ASSEMBLY__) */ -#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 v2.1.43/linux/include/asm-mips/r4kcache.h linux/include/asm-mips/r4kcache.h --- v2.1.43/linux/include/asm-mips/r4kcache.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/r4kcache.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,1025 @@ +/* $Id: r4kcache.h,v 1.1 1997/06/06 09:39:42 ralf Exp $ + * r4kcache.h: Inline assembly cache operations. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _MIPS_R4KCACHE_H +#define _MIPS_R4KCACHE_H + +#include + +extern inline void flush_icache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Invalidate_I)); +} + +extern inline void flush_dcache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Writeback_Inv_D)); +} + +extern inline void flush_scache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Writeback_Inv_SD)); +} + +extern inline void flush_icache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_I)); +} + +extern inline void flush_dcache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Writeback_Inv_D)); +} + +extern inline void flush_scache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Writeback_Inv_SD)); +} + +extern inline void blast_dcache16(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + dcache_size); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x010(%0) + cache %1, 0x020(%0); cache %1, 0x030(%0) + cache %1, 0x040(%0); cache %1, 0x050(%0) + cache %1, 0x060(%0); cache %1, 0x070(%0) + cache %1, 0x080(%0); cache %1, 0x090(%0) + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) + cache %1, 0x100(%0); cache %1, 0x110(%0) + cache %1, 0x120(%0); cache %1, 0x130(%0) + cache %1, 0x140(%0); cache %1, 0x150(%0) + cache %1, 0x160(%0); cache %1, 0x170(%0) + cache %1, 0x180(%0); cache %1, 0x190(%0) + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_D)); + start += 0x200; + } +} + +extern inline void blast_dcache16_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x010(%0) + cache %1, 0x020(%0); cache %1, 0x030(%0) + cache %1, 0x040(%0); cache %1, 0x050(%0) + cache %1, 0x060(%0); cache %1, 0x070(%0) + cache %1, 0x080(%0); cache %1, 0x090(%0) + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) + cache %1, 0x100(%0); cache %1, 0x110(%0) + cache %1, 0x120(%0); cache %1, 0x130(%0) + cache %1, 0x140(%0); cache %1, 0x150(%0) + cache %1, 0x160(%0); cache %1, 0x170(%0) + cache %1, 0x180(%0); cache %1, 0x190(%0) + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) + cache %1, 0x200(%0); cache %1, 0x210(%0) + cache %1, 0x220(%0); cache %1, 0x230(%0) + cache %1, 0x240(%0); cache %1, 0x250(%0) + cache %1, 0x260(%0); cache %1, 0x270(%0) + cache %1, 0x280(%0); cache %1, 0x290(%0) + cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) + cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) + cache %1, 0x300(%0); cache %1, 0x310(%0) + cache %1, 0x320(%0); cache %1, 0x330(%0) + cache %1, 0x340(%0); cache %1, 0x350(%0) + cache %1, 0x360(%0); cache %1, 0x370(%0) + cache %1, 0x380(%0); cache %1, 0x390(%0) + cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) + cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) + cache %1, 0x400(%0); cache %1, 0x410(%0) + cache %1, 0x420(%0); cache %1, 0x430(%0) + cache %1, 0x440(%0); cache %1, 0x450(%0) + cache %1, 0x460(%0); cache %1, 0x470(%0) + cache %1, 0x480(%0); cache %1, 0x490(%0) + cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) + cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) + cache %1, 0x500(%0); cache %1, 0x510(%0) + cache %1, 0x520(%0); cache %1, 0x530(%0) + cache %1, 0x540(%0); cache %1, 0x550(%0) + cache %1, 0x560(%0); cache %1, 0x570(%0) + cache %1, 0x580(%0); cache %1, 0x590(%0) + cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) + cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) + cache %1, 0x600(%0); cache %1, 0x610(%0) + cache %1, 0x620(%0); cache %1, 0x630(%0) + cache %1, 0x640(%0); cache %1, 0x650(%0) + cache %1, 0x660(%0); cache %1, 0x670(%0) + cache %1, 0x680(%0); cache %1, 0x690(%0) + cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) + cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) + cache %1, 0x700(%0); cache %1, 0x710(%0) + cache %1, 0x720(%0); cache %1, 0x730(%0) + cache %1, 0x740(%0); cache %1, 0x750(%0) + cache %1, 0x760(%0); cache %1, 0x770(%0) + cache %1, 0x780(%0); cache %1, 0x790(%0) + cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) + cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Hit_Writeback_Inv_D)); + start += 0x800; + } +} + +extern inline void blast_dcache16_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x010(%0) + cache %1, 0x020(%0); cache %1, 0x030(%0) + cache %1, 0x040(%0); cache %1, 0x050(%0) + cache %1, 0x060(%0); cache %1, 0x070(%0) + cache %1, 0x080(%0); cache %1, 0x090(%0) + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) + cache %1, 0x100(%0); cache %1, 0x110(%0) + cache %1, 0x120(%0); cache %1, 0x130(%0) + cache %1, 0x140(%0); cache %1, 0x150(%0) + cache %1, 0x160(%0); cache %1, 0x170(%0) + cache %1, 0x180(%0); cache %1, 0x190(%0) + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) + cache %1, 0x200(%0); cache %1, 0x210(%0) + cache %1, 0x220(%0); cache %1, 0x230(%0) + cache %1, 0x240(%0); cache %1, 0x250(%0) + cache %1, 0x260(%0); cache %1, 0x270(%0) + cache %1, 0x280(%0); cache %1, 0x290(%0) + cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) + cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) + cache %1, 0x300(%0); cache %1, 0x310(%0) + cache %1, 0x320(%0); cache %1, 0x330(%0) + cache %1, 0x340(%0); cache %1, 0x350(%0) + cache %1, 0x360(%0); cache %1, 0x370(%0) + cache %1, 0x380(%0); cache %1, 0x390(%0) + cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) + cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) + cache %1, 0x400(%0); cache %1, 0x410(%0) + cache %1, 0x420(%0); cache %1, 0x430(%0) + cache %1, 0x440(%0); cache %1, 0x450(%0) + cache %1, 0x460(%0); cache %1, 0x470(%0) + cache %1, 0x480(%0); cache %1, 0x490(%0) + cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) + cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) + cache %1, 0x500(%0); cache %1, 0x510(%0) + cache %1, 0x520(%0); cache %1, 0x530(%0) + cache %1, 0x540(%0); cache %1, 0x550(%0) + cache %1, 0x560(%0); cache %1, 0x570(%0) + cache %1, 0x580(%0); cache %1, 0x590(%0) + cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) + cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) + cache %1, 0x600(%0); cache %1, 0x610(%0) + cache %1, 0x620(%0); cache %1, 0x630(%0) + cache %1, 0x640(%0); cache %1, 0x650(%0) + cache %1, 0x660(%0); cache %1, 0x670(%0) + cache %1, 0x680(%0); cache %1, 0x690(%0) + cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) + cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) + cache %1, 0x700(%0); cache %1, 0x710(%0) + cache %1, 0x720(%0); cache %1, 0x730(%0) + cache %1, 0x740(%0); cache %1, 0x750(%0) + cache %1, 0x760(%0); cache %1, 0x770(%0) + cache %1, 0x780(%0); cache %1, 0x790(%0) + cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) + cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_D)); + start += 0x800; + } +} + +extern inline void blast_dcache32(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + dcache_size); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x020(%0) + cache %1, 0x040(%0); cache %1, 0x060(%0) + cache %1, 0x080(%0); cache %1, 0x0a0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) + cache %1, 0x100(%0); cache %1, 0x120(%0) + cache %1, 0x140(%0); cache %1, 0x160(%0) + cache %1, 0x180(%0); cache %1, 0x1a0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) + cache %1, 0x200(%0); cache %1, 0x220(%0) + cache %1, 0x240(%0); cache %1, 0x260(%0) + cache %1, 0x280(%0); cache %1, 0x2a0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) + cache %1, 0x300(%0); cache %1, 0x320(%0) + cache %1, 0x340(%0); cache %1, 0x360(%0) + cache %1, 0x380(%0); cache %1, 0x3a0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) + cache %1, 0x400(%0); cache %1, 0x420(%0) + cache %1, 0x440(%0); cache %1, 0x460(%0) + cache %1, 0x480(%0); cache %1, 0x4a0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) + cache %1, 0x500(%0); cache %1, 0x520(%0) + cache %1, 0x540(%0); cache %1, 0x560(%0) + cache %1, 0x580(%0); cache %1, 0x5a0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) + cache %1, 0x600(%0); cache %1, 0x620(%0) + cache %1, 0x640(%0); cache %1, 0x660(%0) + cache %1, 0x680(%0); cache %1, 0x6a0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) + cache %1, 0x700(%0); cache %1, 0x720(%0) + cache %1, 0x740(%0); cache %1, 0x760(%0) + cache %1, 0x780(%0); cache %1, 0x7a0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_D)); + start += 0x400; + } +} + +extern inline void blast_dcache32_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x020(%0) + cache %1, 0x040(%0); cache %1, 0x060(%0) + cache %1, 0x080(%0); cache %1, 0x0a0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) + cache %1, 0x100(%0); cache %1, 0x120(%0) + cache %1, 0x140(%0); cache %1, 0x160(%0) + cache %1, 0x180(%0); cache %1, 0x1a0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) + cache %1, 0x200(%0); cache %1, 0x220(%0) + cache %1, 0x240(%0); cache %1, 0x260(%0) + cache %1, 0x280(%0); cache %1, 0x2a0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) + cache %1, 0x300(%0); cache %1, 0x320(%0) + cache %1, 0x340(%0); cache %1, 0x360(%0) + cache %1, 0x380(%0); cache %1, 0x3a0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) + cache %1, 0x400(%0); cache %1, 0x420(%0) + cache %1, 0x440(%0); cache %1, 0x460(%0) + cache %1, 0x480(%0); cache %1, 0x4a0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) + cache %1, 0x500(%0); cache %1, 0x520(%0) + cache %1, 0x540(%0); cache %1, 0x560(%0) + cache %1, 0x580(%0); cache %1, 0x5a0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) + cache %1, 0x600(%0); cache %1, 0x620(%0) + cache %1, 0x640(%0); cache %1, 0x660(%0) + cache %1, 0x680(%0); cache %1, 0x6a0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) + cache %1, 0x700(%0); cache %1, 0x720(%0) + cache %1, 0x740(%0); cache %1, 0x760(%0) + cache %1, 0x780(%0); cache %1, 0x7a0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Hit_Writeback_Inv_D)); + start += 0x800; + } +} + +extern inline void blast_dcache32_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x020(%0) + cache %1, 0x040(%0); cache %1, 0x060(%0) + cache %1, 0x080(%0); cache %1, 0x0a0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) + cache %1, 0x100(%0); cache %1, 0x120(%0) + cache %1, 0x140(%0); cache %1, 0x160(%0) + cache %1, 0x180(%0); cache %1, 0x1a0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) + cache %1, 0x200(%0); cache %1, 0x220(%0) + cache %1, 0x240(%0); cache %1, 0x260(%0) + cache %1, 0x280(%0); cache %1, 0x2a0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) + cache %1, 0x300(%0); cache %1, 0x320(%0) + cache %1, 0x340(%0); cache %1, 0x360(%0) + cache %1, 0x380(%0); cache %1, 0x3a0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) + cache %1, 0x400(%0); cache %1, 0x420(%0) + cache %1, 0x440(%0); cache %1, 0x460(%0) + cache %1, 0x480(%0); cache %1, 0x4a0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) + cache %1, 0x500(%0); cache %1, 0x520(%0) + cache %1, 0x540(%0); cache %1, 0x560(%0) + cache %1, 0x580(%0); cache %1, 0x5a0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) + cache %1, 0x600(%0); cache %1, 0x620(%0) + cache %1, 0x640(%0); cache %1, 0x660(%0) + cache %1, 0x680(%0); cache %1, 0x6a0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) + cache %1, 0x700(%0); cache %1, 0x720(%0) + cache %1, 0x740(%0); cache %1, 0x760(%0) + cache %1, 0x780(%0); cache %1, 0x7a0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Invalidate_I)); + start += 0x800; + } +} + +extern inline void blast_icache16(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + icache_size); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x010(%0) + cache %1, 0x020(%0); cache %1, 0x030(%0) + cache %1, 0x040(%0); cache %1, 0x050(%0) + cache %1, 0x060(%0); cache %1, 0x070(%0) + cache %1, 0x080(%0); cache %1, 0x090(%0) + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) + cache %1, 0x100(%0); cache %1, 0x110(%0) + cache %1, 0x120(%0); cache %1, 0x130(%0) + cache %1, 0x140(%0); cache %1, 0x150(%0) + cache %1, 0x160(%0); cache %1, 0x170(%0) + cache %1, 0x180(%0); cache %1, 0x190(%0) + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Invalidate_I)); + start += 0x200; + } +} + +extern inline void blast_icache16_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x010(%0) + cache %1, 0x020(%0); cache %1, 0x030(%0) + cache %1, 0x040(%0); cache %1, 0x050(%0) + cache %1, 0x060(%0); cache %1, 0x070(%0) + cache %1, 0x080(%0); cache %1, 0x090(%0) + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) + cache %1, 0x100(%0); cache %1, 0x110(%0) + cache %1, 0x120(%0); cache %1, 0x130(%0) + cache %1, 0x140(%0); cache %1, 0x150(%0) + cache %1, 0x160(%0); cache %1, 0x170(%0) + cache %1, 0x180(%0); cache %1, 0x190(%0) + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) + cache %1, 0x200(%0); cache %1, 0x210(%0) + cache %1, 0x220(%0); cache %1, 0x230(%0) + cache %1, 0x240(%0); cache %1, 0x250(%0) + cache %1, 0x260(%0); cache %1, 0x270(%0) + cache %1, 0x280(%0); cache %1, 0x290(%0) + cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) + cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) + cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) + cache %1, 0x300(%0); cache %1, 0x310(%0) + cache %1, 0x320(%0); cache %1, 0x330(%0) + cache %1, 0x340(%0); cache %1, 0x350(%0) + cache %1, 0x360(%0); cache %1, 0x370(%0) + cache %1, 0x380(%0); cache %1, 0x390(%0) + cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) + cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) + cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) + cache %1, 0x400(%0); cache %1, 0x410(%0) + cache %1, 0x420(%0); cache %1, 0x430(%0) + cache %1, 0x440(%0); cache %1, 0x450(%0) + cache %1, 0x460(%0); cache %1, 0x470(%0) + cache %1, 0x480(%0); cache %1, 0x490(%0) + cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) + cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) + cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) + cache %1, 0x500(%0); cache %1, 0x510(%0) + cache %1, 0x520(%0); cache %1, 0x530(%0) + cache %1, 0x540(%0); cache %1, 0x550(%0) + cache %1, 0x560(%0); cache %1, 0x570(%0) + cache %1, 0x580(%0); cache %1, 0x590(%0) + cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) + cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) + cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) + cache %1, 0x600(%0); cache %1, 0x610(%0) + cache %1, 0x620(%0); cache %1, 0x630(%0) + cache %1, 0x640(%0); cache %1, 0x650(%0) + cache %1, 0x660(%0); cache %1, 0x670(%0) + cache %1, 0x680(%0); cache %1, 0x690(%0) + cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) + cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) + cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) + cache %1, 0x700(%0); cache %1, 0x710(%0) + cache %1, 0x720(%0); cache %1, 0x730(%0) + cache %1, 0x740(%0); cache %1, 0x750(%0) + cache %1, 0x760(%0); cache %1, 0x770(%0) + cache %1, 0x780(%0); cache %1, 0x790(%0) + cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) + cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) + cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Hit_Invalidate_I)); + start += 0x800; + } +} + +extern inline void blast_icache16_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 0, 0x000(%0); cache 0, 0x010(%0); cache 0, 0x020(%0); cache 0, 0x030(%0) +cache 0, 0x040(%0); cache 0, 0x050(%0); cache 0, 0x060(%0); cache 0, 0x070(%0) +cache 0, 0x080(%0); cache 0, 0x090(%0); cache 0, 0x0a0(%0); cache 0, 0x0b0(%0) +cache 0, 0x0c0(%0); cache 0, 0x0d0(%0); cache 0, 0x0e0(%0); cache 0, 0x0f0(%0) +cache 0, 0x100(%0); cache 0, 0x110(%0); cache 0, 0x120(%0); cache 0, 0x130(%0) +cache 0, 0x140(%0); cache 0, 0x150(%0); cache 0, 0x160(%0); cache 0, 0x170(%0) +cache 0, 0x180(%0); cache 0, 0x190(%0); cache 0, 0x1a0(%0); cache 0, 0x1b0(%0) +cache 0, 0x1c0(%0); cache 0, 0x1d0(%0); cache 0, 0x1e0(%0); cache 0, 0x1f0(%0) +cache 0, 0x200(%0); cache 0, 0x210(%0); cache 0, 0x220(%0); cache 0, 0x230(%0) +cache 0, 0x240(%0); cache 0, 0x250(%0); cache 0, 0x260(%0); cache 0, 0x270(%0) +cache 0, 0x280(%0); cache 0, 0x290(%0); cache 0, 0x2a0(%0); cache 0, 0x2b0(%0) +cache 0, 0x2c0(%0); cache 0, 0x2d0(%0); cache 0, 0x2e0(%0); cache 0, 0x2f0(%0) +cache 0, 0x300(%0); cache 0, 0x310(%0); cache 0, 0x320(%0); cache 0, 0x330(%0) +cache 0, 0x340(%0); cache 0, 0x350(%0); cache 0, 0x360(%0); cache 0, 0x370(%0) +cache 0, 0x380(%0); cache 0, 0x390(%0); cache 0, 0x3a0(%0); cache 0, 0x3b0(%0) +cache 0, 0x3c0(%0); cache 0, 0x3d0(%0); cache 0, 0x3e0(%0); cache 0, 0x3f0(%0) +cache 0, 0x400(%0); cache 0, 0x410(%0); cache 0, 0x420(%0); cache 0, 0x430(%0) +cache 0, 0x440(%0); cache 0, 0x450(%0); cache 0, 0x460(%0); cache 0, 0x470(%0) +cache 0, 0x480(%0); cache 0, 0x490(%0); cache 0, 0x4a0(%0); cache 0, 0x4b0(%0) +cache 0, 0x4c0(%0); cache 0, 0x4d0(%0); cache 0, 0x4e0(%0); cache 0, 0x4f0(%0) +cache 0, 0x500(%0); cache 0, 0x510(%0); cache 0, 0x520(%0); cache 0, 0x530(%0) +cache 0, 0x540(%0); cache 0, 0x550(%0); cache 0, 0x560(%0); cache 0, 0x570(%0) +cache 0, 0x580(%0); cache 0, 0x590(%0); cache 0, 0x5a0(%0); cache 0, 0x5b0(%0) +cache 0, 0x5c0(%0); cache 0, 0x5d0(%0); cache 0, 0x5e0(%0); cache 0, 0x5f0(%0) +cache 0, 0x600(%0); cache 0, 0x610(%0); cache 0, 0x620(%0); cache 0, 0x630(%0) +cache 0, 0x640(%0); cache 0, 0x650(%0); cache 0, 0x660(%0); cache 0, 0x670(%0) +cache 0, 0x680(%0); cache 0, 0x690(%0); cache 0, 0x6a0(%0); cache 0, 0x6b0(%0) +cache 0, 0x6c0(%0); cache 0, 0x6d0(%0); cache 0, 0x6e0(%0); cache 0, 0x6f0(%0) +cache 0, 0x700(%0); cache 0, 0x710(%0); cache 0, 0x720(%0); cache 0, 0x730(%0) +cache 0, 0x740(%0); cache 0, 0x750(%0); cache 0, 0x760(%0); cache 0, 0x770(%0) +cache 0, 0x780(%0); cache 0, 0x790(%0); cache 0, 0x7a0(%0); cache 0, 0x7b0(%0) +cache 0, 0x7c0(%0); cache 0, 0x7d0(%0); cache 0, 0x7e0(%0); cache 0, 0x7f0(%0) +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x800; + } +} + +extern inline void blast_icache32(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + icache_size); + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0); +cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0); +cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0); +cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0); +cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0); +cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0); +cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0); +cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x400; + } +} + +extern inline void blast_icache32_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 16, 0x000(%0); cache 16, 0x020(%0); cache 16, 0x040(%0); cache 16, 0x060(%0); +cache 16, 0x080(%0); cache 16, 0x0a0(%0); cache 16, 0x0c0(%0); cache 16, 0x0e0(%0); +cache 16, 0x100(%0); cache 16, 0x120(%0); cache 16, 0x140(%0); cache 16, 0x160(%0); +cache 16, 0x180(%0); cache 16, 0x1a0(%0); cache 16, 0x1c0(%0); cache 16, 0x1e0(%0); +cache 16, 0x200(%0); cache 16, 0x220(%0); cache 16, 0x240(%0); cache 16, 0x260(%0); +cache 16, 0x280(%0); cache 16, 0x2a0(%0); cache 16, 0x2c0(%0); cache 16, 0x2e0(%0); +cache 16, 0x300(%0); cache 16, 0x320(%0); cache 16, 0x340(%0); cache 16, 0x360(%0); +cache 16, 0x380(%0); cache 16, 0x3a0(%0); cache 16, 0x3c0(%0); cache 16, 0x3e0(%0); +cache 16, 0x400(%0); cache 16, 0x420(%0); cache 16, 0x440(%0); cache 16, 0x460(%0); +cache 16, 0x480(%0); cache 16, 0x4a0(%0); cache 16, 0x4c0(%0); cache 16, 0x4e0(%0); +cache 16, 0x500(%0); cache 16, 0x520(%0); cache 16, 0x540(%0); cache 16, 0x560(%0); +cache 16, 0x580(%0); cache 16, 0x5a0(%0); cache 16, 0x5c0(%0); cache 16, 0x5e0(%0); +cache 16, 0x600(%0); cache 16, 0x620(%0); cache 16, 0x640(%0); cache 16, 0x660(%0); +cache 16, 0x680(%0); cache 16, 0x6a0(%0); cache 16, 0x6c0(%0); cache 16, 0x6e0(%0); +cache 16, 0x700(%0); cache 16, 0x720(%0); cache 16, 0x740(%0); cache 16, 0x760(%0); +cache 16, 0x780(%0); cache 16, 0x7a0(%0); cache 16, 0x7c0(%0); cache 16, 0x7e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x800; + } +} + +extern inline void blast_icache32_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0); +cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0); +cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0); +cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0); +cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0); +cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0); +cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0); +cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0); +cache 0, 0x400(%0); cache 0, 0x420(%0); cache 0, 0x440(%0); cache 0, 0x460(%0); +cache 0, 0x480(%0); cache 0, 0x4a0(%0); cache 0, 0x4c0(%0); cache 0, 0x4e0(%0); +cache 0, 0x500(%0); cache 0, 0x520(%0); cache 0, 0x540(%0); cache 0, 0x560(%0); +cache 0, 0x580(%0); cache 0, 0x5a0(%0); cache 0, 0x5c0(%0); cache 0, 0x5e0(%0); +cache 0, 0x600(%0); cache 0, 0x620(%0); cache 0, 0x640(%0); cache 0, 0x660(%0); +cache 0, 0x680(%0); cache 0, 0x6a0(%0); cache 0, 0x6c0(%0); cache 0, 0x6e0(%0); +cache 0, 0x700(%0); cache 0, 0x720(%0); cache 0, 0x740(%0); cache 0, 0x760(%0); +cache 0, 0x780(%0); cache 0, 0x7a0(%0); cache 0, 0x7c0(%0); cache 0, 0x7e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x800; + } +} + +extern inline void blast_scache16(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0) +cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0) +cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0) +cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0) +cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0) +cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0) +cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0) +cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0) +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x200; + } +} + +extern inline void blast_scache16_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 23, 0x000(%0); cache 23, 0x010(%0); cache 23, 0x020(%0); cache 23, 0x030(%0) +cache 23, 0x040(%0); cache 23, 0x050(%0); cache 23, 0x060(%0); cache 23, 0x070(%0) +cache 23, 0x080(%0); cache 23, 0x090(%0); cache 23, 0x0a0(%0); cache 23, 0x0b0(%0) +cache 23, 0x0c0(%0); cache 23, 0x0d0(%0); cache 23, 0x0e0(%0); cache 23, 0x0f0(%0) +cache 23, 0x100(%0); cache 23, 0x110(%0); cache 23, 0x120(%0); cache 23, 0x130(%0) +cache 23, 0x140(%0); cache 23, 0x150(%0); cache 23, 0x160(%0); cache 23, 0x170(%0) +cache 23, 0x180(%0); cache 23, 0x190(%0); cache 23, 0x1a0(%0); cache 23, 0x1b0(%0) +cache 23, 0x1c0(%0); cache 23, 0x1d0(%0); cache 23, 0x1e0(%0); cache 23, 0x1f0(%0) +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x200; + } +} + +extern inline void blast_scache16_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0) +cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0) +cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0) +cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0) +cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0) +cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0) +cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0) +cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0) +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x200; + } +} + +extern inline void blast_scache32(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0); +cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0); +cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0); +cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0); +cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0); +cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0); +cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0); +cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x400; + } +} + +extern inline void blast_scache32_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 23, 0x000(%0); cache 23, 0x020(%0); cache 23, 0x040(%0); cache 23, 0x060(%0); +cache 23, 0x080(%0); cache 23, 0x0a0(%0); cache 23, 0x0c0(%0); cache 23, 0x0e0(%0); +cache 23, 0x100(%0); cache 23, 0x120(%0); cache 23, 0x140(%0); cache 23, 0x160(%0); +cache 23, 0x180(%0); cache 23, 0x1a0(%0); cache 23, 0x1c0(%0); cache 23, 0x1e0(%0); +cache 23, 0x200(%0); cache 23, 0x220(%0); cache 23, 0x240(%0); cache 23, 0x260(%0); +cache 23, 0x280(%0); cache 23, 0x2a0(%0); cache 23, 0x2c0(%0); cache 23, 0x2e0(%0); +cache 23, 0x300(%0); cache 23, 0x320(%0); cache 23, 0x340(%0); cache 23, 0x360(%0); +cache 23, 0x380(%0); cache 23, 0x3a0(%0); cache 23, 0x3c0(%0); cache 23, 0x3e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x400; + } +} + +extern inline void blast_scache32_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" +.set noreorder +.set mips3 +cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0); +cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0); +cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0); +cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0); +cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0); +cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0); +cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0); +cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0); +.set mips0 +.set reorder + " : : "r" (start)); + start += 0x400; + } +} + +extern inline void blast_scache64(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x040(%0) + cache %1, 0x080(%0); cache %1, 0x0c0(%0) + cache %1, 0x100(%0); cache %1, 0x140(%0) + cache %1, 0x180(%0); cache %1, 0x1c0(%0) + cache %1, 0x200(%0); cache %1, 0x240(%0) + cache %1, 0x280(%0); cache %1, 0x2c0(%0) + cache %1, 0x300(%0); cache %1, 0x340(%0) + cache %1, 0x380(%0); cache %1, 0x3c0(%0) + cache %1, 0x400(%0); cache %1, 0x440(%0) + cache %1, 0x480(%0); cache %1, 0x4c0(%0) + cache %1, 0x500(%0); cache %1, 0x540(%0) + cache %1, 0x580(%0); cache %1, 0x5c0(%0) + cache %1, 0x600(%0); cache %1, 0x640(%0) + cache %1, 0x680(%0); cache %1, 0x6c0(%0) + cache %1, 0x700(%0); cache %1, 0x740(%0) + cache %1, 0x780(%0); cache %1, 0x7c0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_SD)); + start += 0x800; + } +} + +extern inline void blast_scache64_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x040(%0) + cache %1, 0x080(%0); cache %1, 0x0c0(%0) + cache %1, 0x100(%0); cache %1, 0x140(%0) + cache %1, 0x180(%0); cache %1, 0x1c0(%0) + cache %1, 0x200(%0); cache %1, 0x240(%0) + cache %1, 0x280(%0); cache %1, 0x2c0(%0) + cache %1, 0x300(%0); cache %1, 0x340(%0) + cache %1, 0x380(%0); cache %1, 0x3c0(%0) + cache %1, 0x400(%0); cache %1, 0x440(%0) + cache %1, 0x480(%0); cache %1, 0x4c0(%0) + cache %1, 0x500(%0); cache %1, 0x540(%0) + cache %1, 0x580(%0); cache %1, 0x5c0(%0) + cache %1, 0x600(%0); cache %1, 0x640(%0) + cache %1, 0x680(%0); cache %1, 0x6c0(%0) + cache %1, 0x700(%0); cache %1, 0x740(%0) + cache %1, 0x780(%0); cache %1, 0x7c0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Hit_Writeback_Inv_D)); + start += 0x800; + } +} + +extern inline void blast_scache64_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x040(%0) + cache %1, 0x080(%0); cache %1, 0x0c0(%0) + cache %1, 0x100(%0); cache %1, 0x140(%0) + cache %1, 0x180(%0); cache %1, 0x1c0(%0) + cache %1, 0x200(%0); cache %1, 0x240(%0) + cache %1, 0x280(%0); cache %1, 0x2c0(%0) + cache %1, 0x300(%0); cache %1, 0x340(%0) + cache %1, 0x380(%0); cache %1, 0x3c0(%0) + cache %1, 0x400(%0); cache %1, 0x440(%0) + cache %1, 0x480(%0); cache %1, 0x4c0(%0) + cache %1, 0x500(%0); cache %1, 0x540(%0) + cache %1, 0x580(%0); cache %1, 0x5c0(%0) + cache %1, 0x600(%0); cache %1, 0x640(%0) + cache %1, 0x680(%0); cache %1, 0x6c0(%0) + cache %1, 0x700(%0); cache %1, 0x740(%0) + cache %1, 0x780(%0); cache %1, 0x7c0(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_SD)); + start += 0x800; + } +} + +extern inline void blast_scache128(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x080(%0) + cache %1, 0x100(%0); cache %1, 0x180(%0) + cache %1, 0x200(%0); cache %1, 0x280(%0) + cache %1, 0x300(%0); cache %1, 0x380(%0) + cache %1, 0x400(%0); cache %1, 0x480(%0) + cache %1, 0x500(%0); cache %1, 0x580(%0) + cache %1, 0x600(%0); cache %1, 0x680(%0) + cache %1, 0x700(%0); cache %1, 0x780(%0) + cache %1, 0x800(%0); cache %1, 0x880(%0) + cache %1, 0x900(%0); cache %1, 0x980(%0) + cache %1, 0xa00(%0); cache %1, 0xa80(%0) + cache %1, 0xb00(%0); cache %1, 0xb80(%0) + cache %1, 0xc00(%0); cache %1, 0xc80(%0) + cache %1, 0xd00(%0); cache %1, 0xd80(%0) + cache %1, 0xe00(%0); cache %1, 0xe80(%0) + cache %1, 0xf00(%0); cache %1, 0xf80(%0) + .set mips0 + .set reorder" + : + : "r" (start), + "i" (Index_Writeback_Inv_SD)); + start += 0x1000; + } +} + +extern inline void blast_scache128_page(unsigned long page) +{ + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x080(%0) + cache %1, 0x100(%0); cache %1, 0x180(%0) + cache %1, 0x200(%0); cache %1, 0x280(%0) + cache %1, 0x300(%0); cache %1, 0x380(%0) + cache %1, 0x400(%0); cache %1, 0x480(%0) + cache %1, 0x500(%0); cache %1, 0x580(%0) + cache %1, 0x600(%0); cache %1, 0x680(%0) + cache %1, 0x700(%0); cache %1, 0x780(%0) + cache %1, 0x800(%0); cache %1, 0x880(%0) + cache %1, 0x900(%0); cache %1, 0x980(%0) + cache %1, 0xa00(%0); cache %1, 0xa80(%0) + cache %1, 0xb00(%0); cache %1, 0xb80(%0) + cache %1, 0xc00(%0); cache %1, 0xc80(%0) + cache %1, 0xd00(%0); cache %1, 0xd80(%0) + cache %1, 0xe00(%0); cache %1, 0xe80(%0) + cache %1, 0xf00(%0); cache %1, 0xf80(%0) + .set mips0 + .set reorder" + : + : "r" (page), + "i" (Hit_Writeback_Inv_D)); +} + +extern inline void blast_scache128_page_indexed(unsigned long page) +{ + __asm__ __volatile__(" + .set noreorder + .set mips3 + cache %1, 0x000(%0); cache %1, 0x080(%0) + cache %1, 0x100(%0); cache %1, 0x180(%0) + cache %1, 0x200(%0); cache %1, 0x280(%0) + cache %1, 0x300(%0); cache %1, 0x380(%0) + cache %1, 0x400(%0); cache %1, 0x480(%0) + cache %1, 0x500(%0); cache %1, 0x580(%0) + cache %1, 0x600(%0); cache %1, 0x680(%0) + cache %1, 0x700(%0); cache %1, 0x780(%0) + cache %1, 0x800(%0); cache %1, 0x880(%0) + cache %1, 0x900(%0); cache %1, 0x980(%0) + cache %1, 0xa00(%0); cache %1, 0xa80(%0) + cache %1, 0xb00(%0); cache %1, 0xb80(%0) + cache %1, 0xc00(%0); cache %1, 0xc80(%0) + cache %1, 0xd00(%0); cache %1, 0xd80(%0) + cache %1, 0xe00(%0); cache %1, 0xe80(%0) + cache %1, 0xf00(%0); cache %1, 0xf80(%0) + .set mips0 + .set reorder" + : + : "r" (page), + "i" (Index_Writeback_Inv_SD)); +} + +#endif /* !(_MIPS_R4KCACHE_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/reboot.h linux/include/asm-mips/reboot.h --- v2.1.43/linux/include/asm-mips/reboot.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/reboot.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,17 @@ +/* + * 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) 1997 by Ralf Baechle + * + * Declare variables for rebooting. + */ +#ifndef __ASM_MIPS_REBOOT_H +#define __ASM_MIPS_REBOOT_H + +void (*_machine_restart)(char *command); +void (*_machine_halt)(void); +void (*_machine_power_off)(void); + +#endif /* __ASM_MIPS_REBOOT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/reg.h linux/include/asm-mips/reg.h --- v2.1.43/linux/include/asm-mips/reg.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/reg.h Thu Jun 26 12:33:40 1997 @@ -1,5 +1,6 @@ /* - * Makefile for MIPS Linux main source directory + * Various register offset definitions for debuggers, core file + * examiners and whatnot. * * 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 @@ -15,64 +16,53 @@ * 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 +#define EF_REG0 6 +#define EF_REG1 7 +#define EF_REG2 8 +#define EF_REG3 9 +#define EF_REG4 10 +#define EF_REG5 11 +#define EF_REG6 12 +#define EF_REG7 13 +#define EF_REG8 14 +#define EF_REG9 15 +#define EF_REG10 16 +#define EF_REG11 17 +#define EF_REG12 18 +#define EF_REG13 19 +#define EF_REG14 20 +#define EF_REG15 21 +#define EF_REG16 22 +#define EF_REG17 23 +#define EF_REG18 24 +#define EF_REG19 25 +#define EF_REG20 26 +#define EF_REG21 27 +#define EF_REG22 28 +#define EF_REG23 29 +#define EF_REG24 30 +#define EF_REG25 31 /* * k0/k1 unsaved */ -#define EF_REG28 30 -#define EF_REG29 31 -#define EF_REG30 32 -#define EF_REG31 33 +#define EF_REG28 34 +#define EF_REG29 35 +#define EF_REG30 36 +#define EF_REG31 37 /* * Saved special registers */ -#define EF_LO 34 -#define EF_HI 35 +#define EF_LO 38 +#define EF_HI 39 +#define EF_ORIG_REG2 40 +#define EF_ORIG_REG7 41 + +#define EF_CP0_EPC 42 +#define EF_CP0_BADVADDR 43 +#define EF_CP0_STATUS 44 +#define EF_CP0_CAUSE 45 -/* - * 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]) +#define EF_SIZE 180 #endif /* __ASM_MIPS_REG_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h --- v2.1.43/linux/include/asm-mips/resource.h Fri Aug 23 05:30:15 1996 +++ linux/include/asm-mips/resource.h Thu Jun 26 12:33:40 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996 by Ralf Baechle */ #ifndef __ASM_MIPS_RESOURCE_H #define __ASM_MIPS_RESOURCE_H @@ -13,19 +13,18 @@ /* * 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 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_AS 6 /* mapped memory */ +#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 +#define RLIM_NLIMITS 10 /* Number of limit flavors. */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/scatterlist.h linux/include/asm-mips/scatterlist.h --- v2.1.43/linux/include/asm-mips/scatterlist.h Mon Dec 30 03:01:10 1996 +++ linux/include/asm-mips/scatterlist.h Thu Jun 26 12:33:40 1997 @@ -1,5 +1,5 @@ -#ifndef _MIPS_SCATTERLIST_H -#define _MIPS_SCATTERLIST_H +#ifndef __ASM_MIPS_SCATTERLIST_H +#define __ASM_MIPS_SCATTERLIST_H struct scatterlist { char * address; /* Location data is to be transferred to */ @@ -10,4 +10,4 @@ #define ISA_DMA_THRESHOLD (0x00ffffff) -#endif /* !(_MIPS_SCATTERLIST_H) */ +#endif /* __ASM_MIPS_SCATTERLIST_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/segment.h linux/include/asm-mips/segment.h --- v2.1.43/linux/include/asm-mips/segment.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/segment.h Thu Jun 26 12:33:40 1997 @@ -1,188 +1,6 @@ -/* - * include/asm-mips/segment.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 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 miscompiled for - * 32-bit kernels. - */ -#ifndef __ASM_MIPS_SEGMENT_H -#define __ASM_MIPS_SEGMENT_H +#ifndef __ALPHA_SEGMENT_H +#define __ALPHA_SEGMENT_H -#ifndef __LANGUAGE_ASSEMBLY__ -/* - * For memcpy() - */ -#include +/* Only here because we have some old header files that expect it.. */ -/* - * 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 __gcc_barrier() __asm__ __volatile__("": : :"memory") - -/* - * 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 put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))) -#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))) - -/* - * 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); - -/* I should make this use unaligned transfers etc.. */ -static inline void __put_user(unsigned long x, void * y, int size) -{ - __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(); -} - -/* - * For segmented architectures, these are used to specify which segment - * to use for the above functions. - * - * MIPS is not segmented, so these are just dummies. - */ - -#define KERNEL_DS 0 -#define USER_DS 1 - -static inline unsigned long get_fs(void) -{ - return USER_DS; -} - -static inline unsigned long get_ds(void) -{ - return KERNEL_DS; -} - -static inline void set_fs(unsigned long val) -{ -} - -#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 */ +#endif diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h --- v2.1.43/linux/include/asm-mips/semaphore.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/semaphore.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,84 @@ +/* + * SMP- and interrupt-safe semaphores.. + * + * 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. + * + * (C) Copyright 1996 Linus Torvalds, Ralf Baechle + */ +#ifndef __ASM_MIPS_SEMAPHORE_H +#define __ASM_MIPS_SEMAPHORE_H + +#include + +struct semaphore { + atomic_t count; + atomic_t waking; + struct wait_queue * wait; +}; + +#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL }) +#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL }) + +extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); +extern void __up(struct semaphore * sem); + +#define sema_init(sem, val) atomic_set(&((sem)->count), val) + +/* + * These two _must_ execute atomically wrt each other. + * + * This is trivially done with load_locked/store_cond, + * which we have. Let the rest of the losers suck eggs. + */ + +static inline void wake_one_more(struct semaphore * sem) +{ + atomic_inc(&sem->waking); +} + +static inline int waking_non_zero(struct semaphore *sem) +{ + int ret, tmp; + + __asm__ __volatile__( + "1:\tll\t%1,%2\n" + "blez\t%1,2f\n\t" + "subu\t%0,%1,1\n\t" + "sc\t%0,%2\n\t" + "beqz\t%0,1b\n\t" + "2:" + ".text" + : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking)) + : "0"(0)); + + return ret; +} + +extern inline void down(struct semaphore * sem) +{ + if (atomic_dec_return(&sem->count) < 0) + __down(sem); +} + +extern inline int down_interruptible(struct semaphore * sem) +{ + int ret = 0; + if (atomic_dec_return(&sem->count) < 0) + ret = __down_interruptible(sem); + return ret; +} + +/* + * Note! This is subtle. We jump to wake people up only if + * the semaphore was negative (== somebody was waiting on it). + */ +extern inline void up(struct semaphore * sem) +{ + if (atomic_inc_return(&sem->count) <= 0) + __up(sem); +} + +#endif /* __ASM_MIPS_SEMAPHORE_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgi.h linux/include/asm-mips/sgi.h --- v2.1.43/linux/include/asm-mips/sgi.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgi.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,42 @@ +/* $Id: sgi.h,v 1.1 1997/06/06 09:39:54 ralf Exp $ + * sgi.h: Definitions specific to SGI machines. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + */ +#ifndef _MIPS_SGI_H +#define _MIPS_SGI_H + +/* UP=UniProcessor MP=MultiProcessor(capable) */ +enum sgi_mach { + ip4, /* R2k UP */ + ip5, /* R2k MP */ + ip6, /* R3k UP */ + ip7, /* R3k MP */ + ip9, /* R3k UP */ + ip12, /* R3kA UP, Indigo */ + ip15, /* R3kA MP */ + ip17, /* R4K UP */ + ip19, /* R4K MP */ + ip20, /* R4K UP, Indigo */ + ip21, /* TFP MP */ + ip22, /* R4x00 UP, Indigo2 */ + ip25, /* R10k MP */ + ip26, /* TFP UP, Indigo2 */ + ip28, /* R10k UP, Indigo2 */ + ip30, + ip32, +}; + +extern enum sgi_mach sgimach; +extern void sgi_sysinit(void); + +/* Many I/O space registers are byte sized and are contained within + * one byte per word, specifically the MSB, this macro helps out. + */ +#ifdef __MIPSEL__ +#define SGI_MSB(regaddr) (regaddr) +#else +#define SGI_MSB(regaddr) ((regaddr) | 0x3) +#endif + +#endif /* !(_MIPS_SGI_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h --- v2.1.43/linux/include/asm-mips/sgialib.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgialib.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,118 @@ +/* $Id: sgialib.h,v 1.1 1997/06/06 09:39:56 ralf Exp $ + * sgialib.h: SGI ARCS firmware interface library for the Linux kernel. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#ifndef _MIPS_SGIALIB_H +#define _MIPS_SGIALIB_H + +#include + +extern struct linux_promblock *sgi_pblock; +extern struct linux_romvec *romvec; +extern int prom_argc; +extern char **prom_argv, **prom_envp; + +/* Init the PROM library and it's internal data structures. Called + * at boot time from head.S before start_kernel is invoked. + */ +extern int prom_init(int argc, char **argv, char **envp); + +/* Simple char-by-char console I/O. */ +extern void prom_putchar(char c); +extern char prom_getchar(void); + +/* Generic printf() using ARCS console I/O. */ +extern void prom_printf(char *fmt, ...); + +/* Memory descriptor management. */ +#define PROM_MAX_PMEMBLOCKS 32 +struct prom_pmemblock { + unsigned long base; /* Within KSEG0. */ + unsigned int size; /* In bytes. */ +}; + +/* Get next memory descriptor after CURR, returns first descriptor + * in chain is CURR is NULL. + */ +extern struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr); +#define PROM_NULL_MDESC ((struct linux_mdesc *) 0) + +/* Called by prom_init to setup the physical memory pmemblock + * array. + */ +extern void prom_meminit(void); +extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); + +/* Returns pointer to PROM physical memory block array. */ +extern struct prom_pmemblock *prom_getpblock_array(void); + +/* PROM device tree library routines. */ +#define PROM_NULL_COMPONENT ((pcomponent *) 0) + +/* Get sibling component of THIS. */ +extern pcomponent *prom_getsibling(pcomponent *this); + +/* Get child component of THIS. */ +extern pcomponent *prom_getchild(pcomponent *this); + +/* Get parent component of CHILD. */ +extern pcomponent *prom_getparent(pcomponent *child); + +/* Copy component opaque data of component THIS into BUFFER + * if component THIS has opaque data. Returns success or + * failure status. + */ +extern long prom_getcdata(void *buffer, pcomponent *this); + +/* Other misc. component routines. */ +extern pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data); +extern long prom_delcomponent(pcomponent *this); +extern pcomponent *prom_componentbypath(char *path); + +/* This is called at prom_init time to setup the tags which the + * MIPS kernel setup code wants to diddle with. + */ +extern void prom_setup_archtags(void); + +/* Environemt variable routines. */ +extern char *prom_getenv(char *name); +extern long prom_setenv(char *name, char *value); + +/* ARCS command line acquisition and parsing. */ +extern char *prom_getcmdline(void); +extern void prom_init_cmdline(void); + +/* Acquiring info about the current time, etc. */ +extern struct linux_tinfo *prom_gettinfo(void); +extern unsigned long prom_getrtime(void); + +/* File operations. */ +extern long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt); +extern long prom_open(char *name, enum linux_omode md, unsigned long *fd); +extern long prom_close(unsigned long fd); +extern long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt); +extern long prom_getrstatus(unsigned long fd); +extern long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt); +extern long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm); +extern long prom_mount(char *name, enum linux_mountops op); +extern long prom_getfinfo(unsigned long fd, struct linux_finfo *buf); +extern long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk); + +/* Running stand-along programs. */ +extern long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr); +extern long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp); +extern long prom_exec(char *name, long argc, char **argv, char **envp); + +/* Misc. routines. */ +extern void prom_halt(void); +extern void prom_powerdown(void); +extern void prom_restart(void); +extern void prom_reboot(void); +extern void prom_imode(void); +extern long prom_cfgsave(void); +extern struct linux_sysid *prom_getsysid(void); +extern void prom_cacheflush(void); + +#endif /* !(_MIPS_SGIALIB_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgiarcs.h linux/include/asm-mips/sgiarcs.h --- v2.1.43/linux/include/asm-mips/sgiarcs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgiarcs.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,351 @@ +/* $Id: sgiarcs.h,v 1.1 1997/06/06 09:39:58 ralf Exp $ + * SGI ARCS firmware interface defines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#ifndef _MIPS_SGIARCS_H +#define _MIPS_SGIARCS_H + +/* Various ARCS error codes. */ +#define PROM_ESUCCESS 0x00 +#define PROM_E2BIG 0x01 +#define PROM_EACCESS 0x02 +#define PROM_EAGAIN 0x03 +#define PROM_EBADF 0x04 +#define PROM_EBUSY 0x05 +#define PROM_EFAULT 0x06 +#define PROM_EINVAL 0x07 +#define PROM_EIO 0x08 +#define PROM_EISDIR 0x09 +#define PROM_EMFILE 0x0a +#define PROM_EMLINK 0x0b +#define PROM_ENAMETOOLONG 0x0c +#define PROM_ENODEV 0x0d +#define PROM_ENOENT 0x0e +#define PROM_ENOEXEC 0x0f +#define PROM_ENOMEM 0x10 +#define PROM_ENOSPC 0x11 +#define PROM_ENOTDIR 0x12 +#define PROM_ENOTTY 0x13 +#define PROM_ENXIO 0x14 +#define PROM_EROFS 0x15 +/* SGI ARCS specific errno's. */ +#define PROM_EADDRNOTAVAIL 0x1f +#define PROM_ETIMEDOUT 0x20 +#define PROM_ECONNABORTED 0x21 +#define PROM_ENOCONNECT 0x22 + +/* Device classes, types, and identifiers for prom + * device inventory queries. + */ +enum linux_devclass { + system, processor, cache, adapter, controller, peripheral, memory +}; + +enum linux_devtypes { + /* Generic stuff. */ + Arc, Cpu, Fpu, + + /* Primary insn and data caches. */ + picache, pdcache, + + /* Secondary insn, data, and combined caches. */ + sicache, sdcache, sccache, + + memdev, eisa_adapter, tc_adapter, scsi_adapter, dti_adapter, + multifunc_adapter, dsk_controller, tp_controller, cdrom_controller, + worm_controller, serial_controller, net_controller, disp_controller, + parallel_controller, ptr_controller, kbd_controller, audio_controller, + misc_controller, disk_peripheral, flpy_peripheral, tp_peripheral, + modem_peripheral, monitor_peripheral, printer_peripheral, + ptr_peripheral, kbd_peripheral, term_peripheral, line_peripheral, + net_peripheral, misc_peripheral, anon +}; + +enum linux_identifier { + bogus, ronly, removable, consin, consout, input, output +}; + +/* A prom device tree component. */ +struct linux_component { + enum linux_devclass class; /* node class */ + enum linux_devtypes type; /* node type */ + enum linux_identifier iflags; /* node flags */ + unsigned short vers; /* node version */ + unsigned short rev; /* node revision */ + unsigned long key; /* completely magic */ + unsigned long amask; /* XXX affinity mask??? */ + unsigned long cdsize; /* size of configuration data */ + unsigned long ilen; /* length of string identifier */ + char *iname; /* string identifier */ +}; +typedef struct linux_component pcomponent; + +struct linux_sysid { + char vend[8], prod[8]; +}; + +/* ARCS prom memory descriptors. */ +enum linux_memtypes { + eblock, /* exception block */ + rvpage, /* ARCS romvec page */ + fcontig, /* Contiguous and free */ + free, /* Generic free memory */ + bmem, /* Borken memory, don't use */ + prog, /* A loaded program resides here */ + atmp, /* ARCS temporary storage area, wish Sparc OpenBoot told this */ + aperm, /* ARCS permanent storage... */ +}; + +struct linux_mdesc { + enum linux_memtypes type; + unsigned long base; + unsigned long pages; +}; + +/* Time of day descriptor. */ +struct linux_tinfo { + unsigned short yr; + unsigned short mnth; + unsigned short day; + unsigned short hr; + unsigned short min; + unsigned short sec; + unsigned short msec; +}; + +/* ARCS virtual dirents. */ +struct linux_vdirent { + unsigned long namelen; + unsigned char attr; + char fname[32]; /* XXX imperical, should be a define */ +}; + +/* Other stuff for files. */ +enum linux_omode { + rdonly, wronly, rdwr, wronly_creat, rdwr_creat, + wronly_ssede, rdwr_ssede, dirent, dirent_creat +}; + +enum linux_seekmode { + absolute, relative +}; + +enum linux_mountops { + media_load, media_unload +}; + +/* This prom has a bolixed design. */ +struct linux_bigint { +#ifdef __MIPSEL__ + unsigned long lo; + long hi; +#else /* !(__MIPSEL__) */ + long hi; + unsigned long lo; +#endif +}; + +struct linux_finfo { + struct linux_bigint begin; + struct linux_bigint end; + struct linux_bigint cur; + enum linux_devtypes dtype; + unsigned long namelen; + unsigned char attr; + char name[32]; /* XXX imperical, should be define */ +}; + +struct linux_romvec { + /* Load an executable image. */ + long (*load)(char *file, unsigned long end, + unsigned long *start_pc, + unsigned long *end_addr); + + /* Invoke a standalong image. */ + long (*invoke)(unsigned long startpc, unsigned long sp, + long argc, char **argv, char **envp); + + /* Load and begin execution of a standalong image. */ + long (*exec)(char *file, long argc, char **argv, char **envp); + + void (*halt)(void); /* Halt the machine. */ + void (*pdown)(void); /* Power down the machine. */ + void (*restart)(void); /* XXX soft reset??? */ + void (*reboot)(void); /* Reboot the machine. */ + void (*imode)(void); /* Enter PROM interactive mode. */ + int _unused1; /* padding */ + + /* PROM device tree interface. */ + pcomponent *(*next_component)(pcomponent *this); + pcomponent *(*child_component)(pcomponent *this); + pcomponent *(*parent_component)(pcomponent *this); + long (*component_data)(void *opaque_data, pcomponent *this); + pcomponent *(*child_add)(pcomponent *this, + pcomponent *tmp, + void *opaque_data); + long (*comp_del)(pcomponent *this); + pcomponent *(*component_by_path)(char *file); + + /* Misc. stuff. */ + long (*cfg_save)(void); + struct linux_sysid *(*get_sysid)(void); + + /* Probing for memory. */ + struct linux_mdesc *(*get_mdesc)(struct linux_mdesc *curr); + long _unused2; /* padding */ + + struct linux_tinfo *(*get_tinfo)(void); + unsigned long (*get_rtime)(void); + + /* File type operations. */ + long (*get_vdirent)(unsigned long fd, struct linux_vdirent *entry, + unsigned long num, unsigned long *count); + long (*open)(char *file, enum linux_omode mode, unsigned long *fd); + long (*close)(unsigned long fd); + long (*read)(unsigned long fd, void *buffer, unsigned long num, + unsigned long *count); + long (*get_rstatus)(unsigned long fd); + long (*write)(unsigned long fd, void *buffer, unsigned long num, + unsigned long *count); + long (*seek)(unsigned long fd, struct linux_bigint *offset, + enum linux_seekmode smode); + long (*mount)(char *file, enum linux_mountops op); + + /* Dealing with firmware environment variables. */ + char *(*get_evar)(char *name); + long (*set_evar)(char *name, char *value); + + long (*get_finfo)(unsigned long fd, struct linux_finfo *buf); + long (*set_finfo)(unsigned long fd, unsigned long flags, + unsigned long mask); + + /* Miscellaneous. */ + void (*cache_flush)(void); +}; + +/* The SGI ARCS parameter block is in a fixed location for standalone + * programs to access PROM facilities easily. + */ +struct linux_promblock { + long magic; /* magic cookie */ +#define PROMBLOCK_MAGIC 0x53435241 + + unsigned long len; /* length of parm block */ + unsigned short ver; /* ARCS firmware version */ + unsigned short rev; /* ARCS firmware revision */ + long *rs_block; /* Restart block. */ + long *dbg_block; /* Debug block. */ + long *gevect; /* XXX General vector??? */ + long *utlbvect; /* XXX UTLB vector??? */ + unsigned long rveclen; /* Size of romvec struct. */ + struct linux_romvec *romvec; /* Function interface. */ + unsigned long pveclen; /* Length of private vector. */ + long *pvector; /* Private vector. */ + long adap_cnt; /* Adapter count. */ + long adap_typ0; /* First adapter type. */ + long adap_vcnt0; /* Adapter 0 vector count. */ + long *adap_vector; /* Adapter 0 vector ptr. */ + long adap_typ1; /* Second adapter type. */ + long adap_vcnt1; /* Adapter 1 vector count. */ + long *adap_vector1; /* Adapter 1 vector ptr. */ + /* More adapter vectors go here... */ +}; + +#define PROMBLOCK ((struct linux_promblock *)0xA0001000UL) +#define ROMVECTOR ((PROMBLOCK)->romvec) + +/* Cache layout parameter block. */ +union linux_cache_key { + struct param { +#ifdef __MIPSEL__ + unsigned short size; + unsigned char lsize; + unsigned char bsize; +#else /* !(__MIPSEL__) */ + unsigned char bsize; + unsigned char lsize; + unsigned short size; +#endif + } info; + unsigned long allinfo; +}; + +/* Configuration data. */ +struct linux_cdata { + char *name; + int mlen; + enum linux_devtypes type; +}; + +/* Common SGI ARCS firmware file descriptors. */ +#define SGIPROM_STDIN 0 +#define SGIPROM_STDOUT 1 + +/* Common SGI ARCS firmware file types. */ +#define SGIPROM_ROFILE 0x01 /* read-only file */ +#define SGIPROM_HFILE 0x02 /* hidden file */ +#define SGIPROM_SFILE 0x04 /* System file */ +#define SGIPROM_AFILE 0x08 /* Archive file */ +#define SGIPROM_DFILE 0x10 /* Directory file */ +#define SGIPROM_DELFILE 0x20 /* Deleted file */ + +/* SGI ARCS boot record information. */ +struct sgi_partition { + unsigned char flag; +#define SGIPART_UNUSED 0x00 +#define SGIPART_ACTIVE 0x80 + + unsigned char shead, ssect, scyl; /* unused */ + unsigned char systype; /* OS type, Irix or NT */ + unsigned char ehead, esect, ecyl; /* unused */ + unsigned char rsect0, rsect1, rsect2, rsect3; + unsigned char tsect0, tsect1, tsect2, tsect3; +}; + +#define SGIBBLOCK_MAGIC 0xaa55 +#define SGIBBLOCK_MAXPART 0x0004 + +struct sgi_bootblock { + unsigned char _unused[446]; + struct sgi_partition partitions[SGIBBLOCK_MAXPART]; + unsigned short magic; +}; + +/* BIOS parameter block. */ +struct sgi_bparm_block { + unsigned short bytes_sect; /* bytes per sector */ + unsigned char sect_clust; /* sectors per cluster */ + unsigned short sect_resv; /* reserved sectors */ + unsigned char nfats; /* # of allocation tables */ + unsigned short nroot_dirents; /* # of root directory entries */ + unsigned short sect_volume; /* sectors in volume */ + unsigned char media_type; /* media descriptor */ + unsigned short sect_fat; /* sectors per allocation table */ + unsigned short sect_track; /* sectors per track */ + unsigned short nheads; /* # of heads */ + unsigned short nhsects; /* # of hidden sectors */ +}; + +struct sgi_bsector { + unsigned char jmpinfo[3]; + unsigned char manuf_name[8]; + struct sgi_bparm_block info; +}; + +/* Debugging block used with SGI symmon symbolic debugger. */ +#define SMB_DEBUG_MAGIC 0xfeeddead +struct linux_smonblock { + unsigned long magic; + void (*handler)(void); /* Breakpoint routine. */ + unsigned long dtable_base; /* Base addr of dbg table. */ + int (*printf)(const char *fmt, ...); + unsigned long btable_base; /* Breakpoint table. */ + unsigned long mpflushreqs; /* SMP cache flush request list. */ + unsigned long ntab; /* Name table. */ + unsigned long stab; /* Symbol table. */ + int smax; /* Max # of symbols. */ +}; + +#endif /* !(_MIPS_SGIARCS_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgidefs.h linux/include/asm-mips/sgidefs.h --- v2.1.43/linux/include/asm-mips/sgidefs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgidefs.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,100 @@ +/* + * 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) 1996 by Ralf Baechle + * + * Definitions commonly used in SGI style code. + */ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * There are compilers out there that don't define _MIPS_ISA, _MIPS_SIM, + * _MIPS_SZINT, _MIPS_SZLONG, _MIPS_SZPTR. So we notify the user about this + * problem. The kernel sources are aware of this problem, so we don't warn + * when compiling the kernel. + */ +#if !defined(_MIPS_ISA) && !defined(__KERNEL__) +#warning "Macro _MIPS_ISA has not been defined by specs file" +#endif + +#if !defined(_MIPS_SIM) && !defined(__KERNEL__) +#warning "Macro _MIPS_SIM has not been defined by specs file" +#endif + +#if !defined(_MIPS_SZINT) && !defined(__KERNEL__) +#warning "Macro _MIPS_SZINT has not been defined by specs file" +#endif + +#if !defined(_MIPS_SZLONG) && !defined(__KERNEL__) +#warning "Macro _MIPS_SZLONG has not been defined by specs file" +#endif + +#if !defined(_MIPS_SZPTR) && !defined(__KERNEL__) +#warning "Macro _MIPS_SZPTR has not been defined by specs file" +#endif + +#if (!defined(_MIPS_ISA) || \ + !defined(_MIPS_SIM) || \ + !defined(_MIPS_SZINT) || \ + !defined(_MIPS_SZLONG) || \ + !defined(_MIPS_SZPTR)) && !defined(__KERNEL__) +#warning "Please update your GCC to GCC 2.7.2-4 or newer" +#endif + +/* + * Now lets try our best to supply some reasonable default values for + * whatever defines GCC didn't supply. This cannot be done correct for + * all possible combinations of options, so be careful with your options + * to GCC. Best bet is to keep your fingers off the a.out GCC and use + * ELF GCC 2.7.2-3 where possible. + */ +#ifndef _MIPS_ISA +#if __mips == 1 +#define _MIPS_ISA _MIPS_ISA_MIPS1 +/* It is impossible to handle the -mips2 case correct. */ +#elif __mips == 3 +#define _MIPS_ISA _MIPS_ISA_MIPS3 +#elif __mips == 4 +#define _MIPS_ISA _MIPS_ISA_MIPS4 +#else /* __mips must be 5 */ +#define _MIPS_ISA _MIPS_ISA_MIPS5 +#endif +#endif +#ifndef _MIPS_SIM +#define _MIPS_SIM _MIPS_SIM_ABI32 +#endif +#ifndef _MIPS_SZINT +#define _MIPS_SZINT 32 +#endif +#ifndef _MIPS_SZLONG +#define _MIPS_SZLONG 32 +#endif +#ifndef _MIPS_SZPTR +#define _MIPS_SZPTR 32 +#endif + +/* + * Definitions for the ISA level + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 + +/* + * Subprogram calling convention + * + * At the moment only _MIPS_SIM_ABI32 is in use. This will change rsn. + * Until GCC 2.8.0 is released don't rely on this definitions because the + * 64bit code is essentially using the 32bit interface model just with + * 64bit registers. + */ +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* __ASM_SGIDEFS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgihpc.h linux/include/asm-mips/sgihpc.h --- v2.1.43/linux/include/asm-mips/sgihpc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgihpc.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,340 @@ +/* $Id: sgihpc.h,v 1.1 1997/06/06 09:40:02 ralf Exp $ + * sgihpc.h: Various HPC I/O controller defines. The HPC is basically + * the approximate functional equivalent of the Sun SYSIO + * on SGI INDY machines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _MIPS_SGIHPC_H +#define _MIPS_SGIHPC_H + +#include + +extern int sgi_has_ioc2; /* to know if we have older ioc1 or ioc2. */ +extern int sgi_guiness; /* GUINESS or FULLHOUSE machine. */ +extern int sgi_boardid; /* Board revision. */ + +/* An HPC dma descriptor. */ +struct hpc_dma_desc { + unsigned long pbuf; /* physical address of data buffer */ + unsigned long cntinfo; /* counter and info bits */ +#define HPCDMA_EOX 0x80000000 /* last desc in chain for tx */ +#define HPCDMA_EOR 0x80000000 /* last desc in chain for rx */ +#define HPCDMA_EOXP 0x40000000 /* end of packet for tx */ +#define HPCDMA_EORP 0x40000000 /* end of packet for rx */ +#define HPCDMA_XIE 0x20000000 /* irq generated when at end of this desc */ +#define HPCDMA_XIU 0x01000000 /* Tx buffer in use by CPU. */ +#define HPCDMA_EIPC 0x00ff0000 /* SEEQ ethernet special xternal bytecount */ +#define HPCDMA_ETXD 0x00008000 /* set to one by HPC when packet tx'd */ +#define HPCDMA_OWN 0x00004000 /* Denotes ring buffer ownership on rx */ +#define HPCDMA_BCNT 0x00003fff /* size in bytes of this dma buffer */ + + unsigned long pnext; /* paddr of next hpc_dma_desc if any */ +}; + +typedef volatile unsigned long hpcreg; + +/* HPC1 stuff. */ + +/* HPC3 stuff. */ + +/* The set of regs for each HPC3 pbus dma channel. */ +struct hpc3_pbus_dmacregs { + hpcreg pbdma_bptr; /* pbus dma channel buffer ptr */ + hpcreg pbdma_dptr; /* pbus dma channel desc ptr */ + char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */ + hpcreg pbdma_ctrl; /* pbus dma channel control reg */ +#define HPC3_PDMACTRL_SEL 0x00000002 /* little endian transfer */ +#define HPC3_PDMACTRL_RCV 0x00000004 /* direction is receive */ +#define HPC3_PDMACTRL_FLSH 0x00000008 /* enable flush for receive DMA */ +#define HPC3_PDMACTRL_ACT 0x00000010 /* start dma transfer */ +#define HPC3_PDMACTRL_LD 0x00000020 /* load enable for ACT */ +#define HPC3_PDMACTRL_RT 0x00000040 /* Use realtime GIO bus servicing */ +#define HPC3_PDMACTRL_HW 0x0000ff00 /* DMA High-water mark */ +#define HPC3_PDMACTRL_FB 0x003f0000 /* Ptr to beginning of fifo */ +#define HPC3_PDMACTRL_FE 0x3f000000 /* Ptr to end of fifo */ + + char _unused2[PAGE_SIZE - (sizeof(hpcreg))]; /* padding */ +}; + +/* The HPC3 scsi registers, this does not include external ones. */ +struct hpc3_scsiregs { + hpcreg cbptr; /* current dma buffer ptr, diagnostic use only */ + hpcreg ndptr; /* next dma descriptor ptr */ + char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */ + hpcreg bcd; /* byte count info */ +#define HPC3_SBCD_BCNTMSK 0x00003fff /* bytes to transfer from/to memory */ +#define HPC3_SBCD_XIE 0x00004000 /* Send IRQ when done with cur buf */ +#define HPC3_SBCD_EOX 0x00008000 /* Indicates this is last buf in chain */ + + hpcreg ctrl; /* control register */ +#define HPC3_SCTRL_IRQ 0x01 /* IRQ asserted, either dma done or parity */ +#define HPC3_SCTRL_ENDIAN 0x02 /* DMA endian mode, 0=big 1=little */ +#define HPC3_SCTRL_DIR 0x04 /* DMA direction, 1=dev2mem 0=mem2dev */ +#define HPC3_SCTRL_FLUSH 0x08 /* Tells HPC3 to flush scsi fifos */ +#define HPC3_SCTRL_ACTIVE 0x10 /* SCSI DMA channel is active */ +#define HPC3_SCTRL_AMASK 0x20 /* DMA active inhibits PIO */ +#define HPC3_SCTRL_CRESET 0x40 /* Resets dma channel and external controller */ +#define HPC3_SCTRL_PERR 0x80 /* Bad parity on HPC3 iface to scsi controller */ + + hpcreg gfptr; /* current GIO fifo ptr */ + hpcreg dfptr; /* current device fifo ptr */ + hpcreg dconfig; /* DMA configuration register */ +#define HPC3_SDCFG_HCLK 0x00001 /* Enable DMA half clock mode */ +#define HPC3_SDCFG_D1 0x00006 /* Cycles to spend in D1 state */ +#define HPC3_SDCFG_D2 0x00038 /* Cycles to spend in D2 state */ +#define HPC3_SDCFG_D3 0x001c0 /* Cycles to spend in D3 state */ +#define HPC3_SDCFG_HWAT 0x00e00 /* DMA high water mark */ +#define HPC3_SDCFG_HW 0x01000 /* Enable 16-bit halfword DMA accesses to scsi */ +#define HPC3_SDCFG_SWAP 0x02000 /* Byte swap all DMA accesses */ +#define HPC3_SDCFG_EPAR 0x04000 /* Enable parity checking for DMA */ +#define HPC3_SDCFG_POLL 0x08000 /* hd_dreq polarity control */ +#define HPC3_SDCFG_ERLY 0x30000 /* hd_dreq behavior control bits */ + + hpcreg pconfig; /* PIO configuration register */ +#define HPC3_SPCFG_P3 0x0003 /* Cycles to spend in P3 state */ +#define HPC3_SPCFG_P2W 0x001c /* Cycles to spend in P2 state for writes */ +#define HPC3_SPCFG_P2R 0x01e0 /* Cycles to spend in P2 state for reads */ +#define HPC3_SPCFG_P1 0x0e00 /* Cycles to spend in P1 state */ +#define HPC3_SPCFG_HW 0x1000 /* Enable 16-bit halfword PIO accesses to scsi */ +#define HPC3_SPCFG_SWAP 0x2000 /* Byte swap all PIO accesses */ +#define HPC3_SPCFG_EPAR 0x4000 /* Enable parity checking for PIO */ +#define HPC3_SPCFG_FUJI 0x8000 /* Fujitsu scsi controller mode for faster dma/pio */ + + char _unused2[PAGE_SIZE - (6 * sizeof(hpcreg))]; /* padding */ +}; + +/* SEEQ ethernet HPC3 registers, only one seeq per HPC3. */ +struct hpc3_ethregs { + /* Receiver registers. */ + hpcreg rx_cbptr; /* current dma buffer ptr, diagnostic use only */ + hpcreg rx_ndptr; /* next dma descriptor ptr */ + char _unused1[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */ + hpcreg rx_bcd; /* byte count info */ +#define HPC3_ERXBCD_BCNTMSK 0x00003fff /* bytes to be sent to memory */ +#define HPC3_ERXBCD_XIE 0x20000000 /* HPC3 interrupts cpu at end of this buf */ +#define HPC3_ERXBCD_EOX 0x80000000 /* flags this as end of descriptor chain */ + + hpcreg rx_ctrl; /* control register */ +#define HPC3_ERXCTRL_STAT50 0x0000003f /* Receive status reg bits of Seeq8003 */ +#define HPC3_ERXCTRL_STAT6 0x00000040 /* Rdonly irq status */ +#define HPC3_ERXCTRL_STAT7 0x00000080 /* Rdonlt old/new status bit from Seeq */ +#define HPC3_ERXCTRL_ENDIAN 0x00000100 /* Endian for dma channel, little=1 big=0 */ +#define HPC3_ERXCTRL_ACTIVE 0x00000200 /* Tells if DMA transfer is in progress */ +#define HPC3_ERXCTRL_AMASK 0x00000400 /* Tells if ACTIVE inhibits PIO's to hpc3 */ +#define HPC3_ERXCTRL_RBO 0x00000800 /* Receive buffer overflow if set to 1 */ + + hpcreg rx_gfptr; /* current GIO fifo ptr */ + hpcreg rx_dfptr; /* current device fifo ptr */ + hpcreg _unused2; /* padding */ + hpcreg rx_reset; /* reset register */ +#define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */ +#define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */ +#define HPC3_ERXRST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */ + + hpcreg rx_dconfig; /* DMA configuration register */ +#define HPC3_ERXDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */ +#define HPC3_ERXDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */ +#define HPC3_ERXDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */ +#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */ +#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */ +#define HPC3_ERXDCFG_FEOP 0x04000 /* Bad packet marker timeout enable */ +#define HPC3_ERXDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */ +#define HPC3_ERXDCFG_PTO 0x30000 /* Programmed timeout value for above two */ + + hpcreg rx_pconfig; /* PIO configuration register */ +#define HPC3_ERXPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */ +#define HPC3_ERXPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */ +#define HPC3_ERXPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */ +#define HPC3_ERXPCFG_TST 0x1000 /* Diagnistic ram test feature bit */ + + char _unused3[PAGE_SIZE - (8 * sizeof(hpcreg))]; /* padding */ + + /* Transmitter registers. */ + hpcreg tx_cbptr; /* current dma buffer ptr, diagnostic use only */ + hpcreg tx_ndptr; /* next dma descriptor ptr */ + char _unused4[PAGE_SIZE - (2 * sizeof(hpcreg))]; /* padding */ + hpcreg tx_bcd; /* byte count info */ +#define HPC3_ETXBCD_BCNTMSK 0x00003fff /* bytes to be read from memory */ +#define HPC3_ETXBCD_ESAMP 0x10000000 /* if set, too late to add descriptor */ +#define HPC3_ETXBCD_XIE 0x20000000 /* Interrupt cpu at end of cur desc */ +#define HPC3_ETXBCD_EOP 0x40000000 /* Last byte of cur buf is end of packet */ +#define HPC3_ETXBCD_EOX 0x80000000 /* This buf is the end of desc chain */ + + hpcreg tx_ctrl; /* control register */ +#define HPC3_ETXCTRL_STAT30 0x0000000f /* Rdonly copy of seeq tx stat reg */ +#define HPC3_ETXCTRL_STAT4 0x00000010 /* Indicate late collision occurred */ +#define HPC3_ETXCTRL_STAT75 0x000000e0 /* Rdonly irq status from seeq */ +#define HPC3_ETXCTRL_ENDIAN 0x00000100 /* Dma channel endian mode, 1=little 0=big */ +#define HPC3_ETXCTRL_ACTIVE 0x00000200 /* DMA tx channel is active */ +#define HPC3_ETXCTRL_AMASK 0x00000400 /* Indicates ACTIVE inhibits PIO's */ + + hpcreg tx_gfptr; /* current GIO fifo ptr */ + hpcreg tx_dfptr; /* current device fifo ptr */ + char _unused5[PAGE_SIZE - (4 * sizeof(hpcreg))]; /* padding */ +}; + +struct hpc3_regs { + /* First regs for the PBUS 8 dma channels. */ + struct hpc3_pbus_dmacregs pbdma0, pbdma1, pbdma2, pbdma3; + struct hpc3_pbus_dmacregs pbdma4, pbdma5, pbdma6, pbdma7; + + /* Now the HPC scsi registers, we get two scsi reg sets. */ + struct hpc3_scsiregs scsi_chan0, scsi_chan1; + + /* The SEEQ hpc3 ethernet dma/control registers. */ + struct hpc3_ethregs ethregs; + + /* Here are where the hpc3 fifo's can be directly accessed + * via PIO accesses. Under normal operation we never stick + * our grubby paws in here so it's just padding. + */ + char _unused1[PAGE_SIZE * 16]; + + /* HPC3 irq status regs. Due to a peculiar bug you need to + * look at two different register addresses to get at all of + * the status bits. The first reg can only reliably report + * bits 4:0 of the status, and the second reg can only + * reliably report bits 9:5 of the hpc3 irq status. I told + * you it was a peculiar bug. ;-) + */ + hpcreg istat0; /* Irq status, only bits <4:0> reliable. */ +#define HPC3_ISTAT_PBIMASK 0x0ff /* irq bits for pbus devs 0 --> 7 */ +#define HPC3_ISTAT_SC0MASK 0x100 /* irq bit for scsi channel 0 */ +#define HPC3_ISTAT_SC1MASK 0x200 /* irq bit for scsi channel 1 */ + + hpcreg gio64_misc; /* GIO64 misc control bits. */ +#define HPC3_GIOMISC_ERTIME 0x1 /* Enable external timer real time. */ +#define HPC3_GIOMISC_DENDIAN 0x2 /* dma descriptor endian, 1=lit 0=big */ + + hpcreg eeprom_data; /* EEPROM data reg. */ +#define HPC3_EEPROM_EPROT 0x01 /* Protect register enable */ +#define HPC3_EEPROM_CSEL 0x02 /* Chip select */ +#define HPC3_EEPROM_ECLK 0x04 /* EEPROM clock */ +#define HPC3_EEPROM_DATO 0x08 /* Data out */ +#define HPC3_EEPROM_DATI 0x10 /* Data in */ + + hpcreg istat1; /* Irq status, only bits <9:5> reliable. */ + hpcreg gio64_estat; /* GIO64 error interrupt status reg. */ +#define HPC3_GIOESTAT_BLMASK 0x000ff /* Bus lane where bad parity occurred */ +#define HPC3_GIOESTAT_CTYPE 0x00100 /* Bus cycle type, 0=PIO 1=DMA */ +#define HPC3_GIOESTAT_PIDMSK 0x3f700 /* DMA channel parity identifier */ + + /* Now direct PIO per-HPC3 peripheral access to external regs. */ + char _unused2[0x13ff0]; /* Trust me... */ + hpcreg scsi0_ext[256]; /* SCSI channel 0 external regs */ + char _unused3[0x07c00]; /* Trust me... */ + hpcreg scsi1_ext[256]; /* SCSI channel 1 external regs */ + char _unused4[0x07c00]; /* It'll only hurt a little... */ + + /* Per-peripheral device external registers and dma/pio control. */ + hpcreg pbus_extregs[256][10]; /* 2nd indice indexes controller */ + hpcreg pbus_dmacfgs[128][10]; /* 2nd indice indexes controller */ +#define HPC3_PIODCFG_D3R 0x00000001 /* Cycles to spend in D3 for reads */ +#define HPC3_PIODCFG_D4R 0x0000001e /* Cycles to spend in D4 for reads */ +#define HPC3_PIODCFG_D5R 0x000001e0 /* Cycles to spend in D5 for reads */ +#define HPC3_PIODCFG_D3W 0x00000200 /* Cycles to spend in D3 for writes */ +#define HPC3_PIODCFG_D4W 0x00003c00 /* Cycles to spend in D4 for writes */ +#define HPC3_PIODCFG_D5W 0x0003c000 /* Cycles to spend in D5 for writes */ +#define HPC3_PIODCFG_HWORD 0x00040000 /* Enable 16-bit dma access mode */ +#define HPC3_PIODCFG_EHI 0x00080000 /* Places halfwords on high 16 bits of bus */ +#define HPC3_PIODCFG_RTIME 0x00200000 /* Make this device real time on GIO bus */ +#define HPC3_PIODCFG_BURST 0x07c00000 /* 5 bit burst count for DMA device */ +#define HPC3_PIODCFG_DRQLV 0x08000000 /* Use live pbus_dreq unsynchronized signal */ + + hpcreg pbus_piocfgs[64][10]; /* 2nd indice indexes controller */ +#define HPC3_PIOPCFG_RP2 0x00001 /* Cycles to spend in P2 state for reads */ +#define HPC3_PIOPCFG_RP3 0x0001e /* Cycles to spend in P3 state for reads */ +#define HPC3_PIOPCFG_RP4 0x001e0 /* Cycles to spend in P4 state for reads */ +#define HPC3_PIOPCFG_WP2 0x00200 /* Cycles to spend in P2 state for writes */ +#define HPC3_PIOPCFG_WP3 0x03c00 /* Cycles to spend in P3 state for writes */ +#define HPC3_PIOPCFG_WP4 0x3c000 /* Cycles to spend in P4 state for writes */ +#define HPC3_PIOPCFG_HW 0x40000 /* Enable 16-bit PIO accesses */ +#define HPC3_PIOPCFG_EHI 0x80000 /* Place even address bits in bits <15:8> */ + + /* PBUS PROM control regs. */ + hpcreg pbus_promwe; /* PROM write enable register */ +#define HPC3_PROM_WENAB 0x1 /* Enable writes to the PROM */ + + char _unused5[0x800 - sizeof(hpcreg)]; + hpcreg pbus_promswap; /* Chip select swap reg */ +#define HPC3_PROM_SWAP 0x1 /* invert GIO addr bit to select prom0 or prom1 */ + + char _unused6[0x800 - sizeof(hpcreg)]; + hpcreg pbus_gout; /* PROM general purpose output reg */ +#define HPC3_PROM_STAT 0x1 /* General purpose status bit in gout */ + + char _unused7[0x1000 - sizeof(hpcreg)]; + hpcreg pbus_promram[16384]; /* 64k of PROM battery backed ram */ +}; + +/* It is possible to have two HPC3's within the address space on + * one machine, though only having one is more likely on an INDY. + * Controller 0 lives at physical address 0x1fb80000 and the controller + * 1 if present lives at address 0x1fb00000. + */ +extern struct hpc3_regs *hpc3c0, *hpc3c1; +#define HPC3_CHIP0_PBASE 0x1fb80000 /* physical */ +#define HPC3_CHIP1_PBASE 0x1fb00000 /* physical */ + +/* Control and misc status information, these live in pbus channel 6. */ +struct hpc3_miscregs { + hpcreg pdata, pctrl, pstat, pdmactrl, pistat, pimask; + hpcreg ptimer1, ptimer2, ptimer3, ptimer4; + hpcreg _unused1[2]; + hpcreg ser1cmd, ser1data; + hpcreg ser0cmd, ser0data; + hpcreg kbdmouse0, kbdmouse1; + hpcreg gcsel, genctrl, panel; + hpcreg _unused2; + hpcreg sysid; + hpcreg _unused3; + hpcreg read, _unused4; + hpcreg dselect; +#define HPC3_DSELECT_SCLK10MHZ 0x00 /* use 10MHZ serial clock */ +#define HPC3_DSELECT_ISDNB 0x01 /* enable isdn B */ +#define HPC3_DSELECT_ISDNA 0x02 /* enable isdn A */ +#define HPC3_DSELECT_LPR 0x04 /* use parallel DMA */ +#define HPC3_DSELECT_SCLK667MHZ 0x10 /* use 6.67MHZ serial clock */ +#define HPC3_DSELECT_SCLKEXT 0x20 /* use external serial clock */ + + hpcreg _unused5; + hpcreg write1; +#define HPC3_WRITE1_PRESET 0x01 /* 0=LPR_RESET, 1=NORMAL */ +#define HPC3_WRITE1_KMRESET 0x02 /* 0=KBDMOUSE_RESET, 1=NORMAL */ +#define HPC3_WRITE1_ERESET 0x04 /* 0=EISA_RESET, 1=NORMAL */ +#define HPC3_WRITE1_GRESET 0x08 /* 0=MAGIC_GIO_RESET, 1=NORMAL */ +#define HPC3_WRITE1_LC0OFF 0x10 /* turn led off (guiness=red, else green) */ +#define HPC3_WRITE1_LC1OFF 0x20 /* turn led off (guiness=green, else amber) */ + + hpcreg _unused6; + hpcreg write2; +#define HPC3_WRITE2_NTHRESH 0x01 /* use 4.5db threshhold */ +#define HPC3_WRITE2_TPSPEED 0x02 /* use 100ohm TP speed */ +#define HPC3_WRITE2_EPSEL 0x04 /* force cable mode: 1=AUI 0=TP */ +#define HPC3_WRITE2_EASEL 0x08 /* 1=autoselect 0=manual cable selection */ +#define HPC3_WRITE2_U1AMODE 0x10 /* 1=PC 0=MAC UART mode */ +#define HPC3_WRITE2_U0AMODE 0x20 /* 1=PC 0=MAC UART mode */ +#define HPC3_WRITE2_MLO 0x40 /* 1=4.75V 0=+5V */ +#define HPC3_WRITE2_MHI 0x80 /* 1=5.25V 0=+5V */ +}; +extern struct hpc3_miscregs *hpc3mregs; +#define HPC3_MREGS_PBASE 0x1fbd9800 /* physical */ + +struct hpc_keyb { +#ifdef __MIPSEB__ + unsigned char _unused0[3]; + volatile unsigned char data; + unsigned char _unused1[3]; + volatile unsigned char command; +#else + volatile unsigned char data; + unsigned char _unused0[3]; + volatile unsigned char command; + unsigned char _unused1[3]; +#endif +}; + +extern void sgihpc_init(void); + +#endif /* !(_MIPS_SGIHPC_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgimc.h linux/include/asm-mips/sgimc.h --- v2.1.43/linux/include/asm-mips/sgimc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgimc.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,223 @@ +/* $Id: sgimc.h,v 1.1 1997/06/06 09:40:04 ralf Exp $ + * sgimc.h: Definitions for memory controller hardware found on + * SGI IP20, IP22, IP26, and IP28 machines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#ifndef _MIPS_SGIMC_H +#define _MIPS_SGIMC_H + +struct sgimc_misc_ctrl { + unsigned long _unused1; + volatile unsigned long cpuctrl0; /* CPU control register 0, readwrite */ +#define SGIMC_CCTRL0_REFS 0x0000000f /* REFS mask */ +#define SGIMC_CCTRL0_EREFRESH 0x00000010 /* Memory refresh enable */ +#define SGIMC_CCTRL0_EPERRGIO 0x00000020 /* GIO parity error enable */ +#define SGIMC_CCTRL0_EPERRMEM 0x00000040 /* Main mem parity error enable */ +#define SGIMC_CCTRL0_EPERRCPU 0x00000080 /* CPU bus parity error enable */ +#define SGIMC_CCTRL0_WDOG 0x00000100 /* Watchdog timer enable */ +#define SGIMC_CCTRL0_SYSINIT 0x00000200 /* System init bit */ +#define SGIMC_CCTRL0_GFXRESET 0x00000400 /* Graphics interface reset */ +#define SGIMC_CCTRL0_EISALOCK 0x00000800 /* Lock CPU from memory for EISA */ +#define SGIMC_CCTRL0_EPERRSCMD 0x00001000 /* SysCMD bus parity error enable */ +#define SGIMC_CCTRL0_IENAB 0x00002000 /* Allow interrupts from MC */ +#define SGIMC_CCTRL0_ESNOOP 0x00004000 /* Snooping I/O enable */ +#define SGIMC_CCTRL0_EPROMWR 0x00008000 /* Prom writes from cpu enable */ +#define SGIMC_CCTRL0_WRESETPMEM 0x00010000 /* Perform warm reset, preserves mem */ +#define SGIMC_CCTRL0_LENDIAN 0x00020000 /* Put MC in little-endian mode */ +#define SGIMC_CCTRL0_WRESETDMEM 0x00040000 /* Warm reset, destroys mem contents */ +#define SGIMC_CCTRL0_CMEMBADPAR 0x02000000 /* Generate bad perr from cpu to mem */ +#define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */ +#define SGIMC_CCTRL0_GIOBTOB 0x08000000 /* Allow GIO back to back writes */ + + unsigned long _unused2; + volatile unsigned long cpuctrl1; /* CPU control register 1, readwrite */ +#define SGIMC_CCTRL1_EGIOTIMEO 0x00000010 /* GIO bus timeout enable */ +#define SGIMC_CCTRL1_FIXEDEHPC 0x00001000 /* Fixed HPC endianness */ +#define SGIMC_CCTRL1_LITTLEHPC 0x00002000 /* Little endian HPC */ +#define SGIMC_CCTRL1_FIXEDEEXP0 0x00004000 /* Fixed EXP0 endianness */ +#define SGIMC_CCTRL1_LITTLEEXP0 0x00008000 /* Little endian EXP0 */ +#define SGIMC_CCTRL1_FIXEDEEXP1 0x00010000 /* Fixed EXP1 endianness */ +#define SGIMC_CCTRL1_LITTLEEXP1 0x00020000 /* Little endian EXP1 */ + + unsigned long _unused3; + volatile unsigned long watchdogt; /* Watchdog reg rdonly, write clears */ + + unsigned long _unused4; + volatile unsigned long systemid; /* MC system ID register, readonly */ +#define SGIMC_SYSID_MASKREV 0x0000000f /* Revision of MC controller */ +#define SGIMC_SYSID_EPRESENT 0x00000010 /* Indicates presence of EISA bus */ + + unsigned long _unused5[3]; + volatile unsigned long divider; /* Divider reg for RPSS */ + + unsigned long _unused6; + volatile unsigned char eeprom; /* EEPROM byte reg for r4k */ +#define SGIMC_EEPROM_PRE 0x00000001 /* eeprom chip PRE pin assertion */ +#define SGIMC_EEPROM_CSEL 0x00000002 /* Active high, eeprom chip select */ +#define SGIMC_EEPROM_SECLOCK 0x00000004 /* EEPROM serial clock */ +#define SGIMC_EEPROM_SDATAO 0x00000008 /* Serial EEPROM data-out */ +#define SGIMC_EEPROM_SDATAI 0x00000010 /* Serial EEPROM data-in */ + + unsigned char _unused7[3]; + unsigned long _unused8[3]; + volatile unsigned short rcntpre; /* Preload refresh counter */ + + unsigned short _unused9; + unsigned long _unused9a; + volatile unsigned short rcounter; /* Readonly refresh counter */ + + unsigned short _unused10; + unsigned long _unused11[13]; + volatile unsigned long gioparm; /* Parameter word for GIO64 */ +#define SGIMC_GIOPARM_HPC64 0x00000001 /* HPC talks to GIO using 64-bits */ +#define SGIMC_GIOPARM_GFX64 0x00000002 /* GFX talks to GIO using 64-bits */ +#define SGIMC_GIOPARM_EXP064 0x00000004 /* EXP(slot0) talks using 64-bits */ +#define SGIMC_GIOPARM_EXP164 0x00000008 /* EXP(slot1) talks using 64-bits */ +#define SGIMC_GIOPARM_EISA64 0x00000010 /* EISA bus talks 64-bits to GIO */ +#define SGIMC_GIOPARM_HPC264 0x00000020 /* 2nd HPX talks 64-bits to GIO */ +#define SGIMC_GIOPARM_RTIMEGFX 0x00000040 /* GFX device has realtime attr */ +#define SGIMC_GIOPARM_RTIMEEXP0 0x00000080 /* EXP(slot0) has realtime attr */ +#define SGIMC_GIOPARM_RTIMEEXP1 0x00000100 /* EXP(slot1) has realtime attr */ +#define SGIMC_GIOPARM_MASTEREISA 0x00000200 /* EISA bus can act as bus master */ +#define SGIMC_GIOPARM_ONEBUS 0x00000400 /* Exists one GIO64 pipelined bus */ +#define SGIMC_GIOPARM_MASTERGFX 0x00000800 /* GFX can act as a bus master */ +#define SGIMC_GIOPARM_MASTEREXP0 0x00001000 /* EXP(slot0) can bus master */ +#define SGIMC_GIOPARM_MASTEREXP1 0x00002000 /* EXP(slot1) can bus master */ +#define SGIMC_GIOPARM_PLINEEXP0 0x00004000 /* EXP(slot0) has pipeline attr */ +#define SGIMC_GIOPARM_PLINEEXP1 0x00008000 /* EXP(slot1) has pipeline attr */ + + unsigned long _unused13; + volatile unsigned short cputp; /* CPU bus arb time period */ + + unsigned short _unused14; + unsigned long _unused15[3]; + volatile unsigned short lbursttp; /* Time period for long bursts */ + + unsigned short _unused16; + unsigned long _unused17[9]; + volatile unsigned long mconfig0; /* Memory config register zero */ + unsigned long _unused18; + volatile unsigned long mconfig1; /* Memory config register one */ + + /* These defines apply to both mconfig registers above. */ +#define SGIMC_MCONFIG_FOURMB 0x00000000 /* Physical ram = 4megs */ +#define SGIMC_MCONFIG_EIGHTMB 0x00000100 /* Physical ram = 8megs */ +#define SGIMC_MCONFIG_SXTEENMB 0x00000300 /* Physical ram = 16megs */ +#define SGIMC_MCONFIG_TTWOMB 0x00000700 /* Physical ram = 32megs */ +#define SGIMC_MCONFIG_SFOURMB 0x00000f00 /* Physical ram = 64megs */ +#define SGIMC_MCONFIG_OTEIGHTMB 0x00001f00 /* Physical ram = 128megs */ +#define SGIMC_MCONFIG_RMASK 0x00001f00 /* Ram config bitmask */ + + unsigned long _unused19; + volatile unsigned long cmacc; /* Mem access config for CPU */ + unsigned long _unused20; + volatile unsigned long gmacc; /* Mem access config for GIO */ + + /* This define applies to both cmacc and gmacc registers above. */ +#define SGIMC_MACC_ALIASBIG 0x20000000 /* 512MB home for alias */ + + /* Error address/status regs from GIO and CPU perspectives. */ + unsigned long _unused21; + volatile unsigned long cerr; /* Error address reg for CPU */ + unsigned long _unused22; + volatile unsigned long cstat; /* Status reg for CPU */ + unsigned long _unused23; + volatile unsigned long gerr; /* Error address reg for GIO */ + unsigned long _unused24; + volatile unsigned long gstat; /* Status reg for GIO */ + + /* Special hard bus locking registers. */ + unsigned long _unused25; + volatile unsigned char syssembit; /* Uni-bit system semaphore */ + unsigned char _unused26[3]; + unsigned long _unused27; + volatile unsigned char mlock; /* Global GIO memory access lock */ + unsigned char _unused28[3]; + unsigned long _unused29; + volatile unsigned char elock; /* Locks EISA from GIO accesses */ + + /* GIO dma control registers. */ + unsigned char _unused30[3]; + unsigned long _unused31[14]; + volatile unsigned long gio_dma_trans;/* DMA mask to translation GIO addrs */ + unsigned long _unused32; + volatile unsigned long gio_dma_sbits;/* DMA GIO addr substitution bits */ + unsigned long _unused33; + volatile unsigned long dma_intr_cause; /* DMA IRQ cause indicator bits */ + unsigned long _unused34; + volatile unsigned long dma_ctrl; /* Main DMA control reg */ + + /* DMA TLB entry 0 */ + unsigned long _unused35; + volatile unsigned long dtlb_hi0; + unsigned long _unused36; + volatile unsigned long dtlb_lo0; + + /* DMA TLB entry 1 */ + unsigned long _unused37; + volatile unsigned long dtlb_hi1; + unsigned long _unused38; + volatile unsigned long dtlb_lo1; + + /* DMA TLB entry 2 */ + unsigned long _unused39; + volatile unsigned long dtlb_hi2; + unsigned long _unused40; + volatile unsigned long dtlb_lo2; + + /* DMA TLB entry 3 */ + unsigned long _unused41; + volatile unsigned long dtlb_hi3; + unsigned long _unused42; + volatile unsigned long dtlb_lo3; +}; + +/* MC misc control registers live at physical 0x1fa00000. */ +extern struct sgimc_misc_ctrl *mcmisc_regs; +extern unsigned long *rpsscounter; /* Chirps at 100ns */ + +struct sgimc_dma_ctrl { + unsigned long _unused1; + volatile unsigned long maddronly; /* Address DMA goes at */ + unsigned long _unused2; + volatile unsigned long maddrpdeflts; /* Same as above, plus set defaults */ + unsigned long _unused3; + volatile unsigned long dmasz; /* DMA count */ + unsigned long _unused4; + volatile unsigned long ssize; /* DMA stride size */ + unsigned long _unused5; + volatile unsigned long gmaddronly; /* Set GIO DMA but do not start trans */ + unsigned long _unused6; + volatile unsigned long dmaddnpgo; /* Set GIO DMA addr + start transfer */ + unsigned long _unused7; + volatile unsigned long dmamode; /* DMA mode config bit settings */ + unsigned long _unused8; + volatile unsigned long dmacount; /* Zoom and byte count for DMA */ + unsigned long _unused9; + volatile unsigned long dmastart; /* Pedal to the metal. */ + unsigned long _unused10; + volatile unsigned long dmarunning; /* DMA op is in progress */ + unsigned long _unused11; + + /* Set dma addr, defaults, and kick it */ + volatile unsigned long maddr_defl_go; /* go go go! -lm */ +}; + +/* MC controller dma regs live at physical 0x1fa02000. */ +extern struct sgimc_dma_ctrl *dmactrlregs; + +/* Base location of the two ram banks found in IP2[0268] machines. */ +#define SGIMC_SEG0_BADDR 0x08000000 +#define SGIMC_SEG1_BADDR 0x20000000 + +/* Maximum size of the above banks are per machine. */ +extern unsigned long sgimc_seg0_size, sgimc_seg1_size; +#define SGIMC_SEG0_SIZE_ALL 0x10000000 /* 256MB */ +#define SGIMC_SEG1_SIZE_IP20_IP22 0x08000000 /* 128MB */ +#define SGIMC_SEG1_SIZE_IP26_IP28 0x20000000 /* 512MB */ + +extern void sgimc_init(void); + +#endif /* !(_MIPS_SGIMC_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sgint23.h linux/include/asm-mips/sgint23.h --- v2.1.43/linux/include/asm-mips/sgint23.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sgint23.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,179 @@ +/* $Id: sgint23.h,v 1.1 1997/06/06 09:40:06 ralf Exp $ + * sgint23.h: Defines for the SGI INT2 and INT3 chipsets. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _MIPS_SGINT23_H +#define _MIPS_SGINT23_H + +/* These are the virtual IRQ numbers, we divide all IRQ's into + * 'spaces', the 'space' determines where and how to enable/disable + * that particular IRQ on an SGI machine. Add new 'spaces' as new + * IRQ hardware is supported. + */ +#define SGINT_LOCAL0 0 /* INDY has 8 local0 irq levels */ +#define SGINT_LOCAL1 8 /* INDY has 8 local1 irq levels */ +#define SGINT_LOCAL2 16 /* INDY has 8 local2 vectored irq levels */ +#define SGINT_LOCAL3 24 /* INDY has 8 local3 vectored irq levels */ +#define SGINT_GIO 32 /* INDY has 9 GIO irq levels */ +#define SGINT_HPCDMA 41 /* INDY has 11 HPCDMA irq _sources_ */ +#define SGINT_END 52 /* End of 'spaces' */ + +/* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */ +#define SGI_INT2_BASE 0x1fb80100 /* physical */ +#define SGI_INT3_BASE 0x1fbd9880 /* physical */ + +struct sgi_ioc_ints { +#ifdef __MIPSEB__ + unsigned char _unused0[3]; + volatile unsigned char istat0; /* Interrupt status zero */ +#else + volatile unsigned char istat0; /* Interrupt status zero */ + unsigned char _unused0[3]; +#endif +#define ISTAT0_FFULL 0x01 +#define ISTAT0_SCSI0 0x02 +#define ISTAT0_SCSI1 0x04 +#define ISTAT0_ENET 0x08 +#define ISTAT0_GFXDMA 0x10 +#define ISTAT0_LPR 0x20 +#define ISTAT0_HPC2 0x40 +#define ISTAT0_LIO2 0x80 + +#ifdef __MIPSEB__ + unsigned char _unused1[3]; + volatile unsigned char imask0; /* Interrupt mask zero */ + unsigned char _unused2[3]; + volatile unsigned char istat1; /* Interrupt status one */ +#else + volatile unsigned char imask0; /* Interrupt mask zero */ + unsigned char _unused1[3]; + volatile unsigned char istat1; /* Interrupt status one */ + unsigned char _unused2[3]; +#endif +#define ISTAT1_ISDNI 0x01 +#define ISTAT1_PWR 0x02 +#define ISTAT1_ISDNH 0x04 +#define ISTAT1_LIO3 0x08 +#define ISTAT1_HPC3 0x10 +#define ISTAT1_AFAIL 0x20 +#define ISTAT1_VIDEO 0x40 +#define ISTAT1_GIO2 0x80 + +#ifdef __MIPSEB__ + unsigned char _unused3[3]; + volatile unsigned char imask1; /* Interrupt mask one */ + unsigned char _unused4[3]; + volatile unsigned char vmeistat; /* VME interrupt status */ + unsigned char _unused5[3]; + volatile unsigned char cmeimask0; /* VME interrupt mask zero */ + unsigned char _unused6[3]; + volatile unsigned char cmeimask1; /* VME interrupt mask one */ + unsigned char _unused7[3]; + volatile unsigned char cmepol; /* VME polarity */ +#else + volatile unsigned char imask1; /* Interrupt mask one */ + unsigned char _unused3[3]; + volatile unsigned char vmeistat; /* VME interrupt status */ + unsigned char _unused4[3]; + volatile unsigned char cmeimask0; /* VME interrupt mask zero */ + unsigned char _unused5[3]; + volatile unsigned char cmeimask1; /* VME interrupt mask one */ + unsigned char _unused6[3]; + volatile unsigned char cmepol; /* VME polarity */ + unsigned char _unused7[3]; +#endif +}; + +struct sgi_ioc_timers { +#ifdef __MIPSEB__ + unsigned char _unused0[3]; + volatile unsigned char tcnt0; /* counter 0 */ + unsigned char _unused1[3]; + volatile unsigned char tcnt1; /* counter 1 */ + unsigned char _unused2[3]; + volatile unsigned char tcnt2; /* counter 2 */ + unsigned char _unused3[3]; + volatile unsigned char tcword; /* control word */ +#else + volatile unsigned char tcnt0; /* counter 0 */ + unsigned char _unused0[3]; + volatile unsigned char tcnt1; /* counter 1 */ + unsigned char _unused1[3]; + volatile unsigned char tcnt2; /* counter 2 */ + unsigned char _unused2[3]; + volatile unsigned char tcword; /* control word */ + unsigned char _unused3[3]; +#endif +}; + +/* Timer control word bits. */ +#define SGINT_TCWORD_BCD 0x01 /* Use BCD mode for counters */ +#define SGINT_TCWORD_MMASK 0x0e /* Mode bitmask. */ +#define SGINT_TCWORD_MITC 0x00 /* IRQ on terminal count (doesn't work) */ +#define SGINT_TCWORD_MOS 0x02 /* One-shot IRQ mode. */ +#define SGINT_TCWORD_MRGEN 0x04 /* Normal rate generation */ +#define SGINT_TCWORD_MSWGEN 0x06 /* Square wave generator mode */ +#define SGINT_TCWORD_MSWST 0x08 /* Software strobe */ +#define SGINT_TCWORD_MHWST 0x0a /* Hardware strobe */ +#define SGINT_TCWORD_CMASK 0x30 /* Command mask */ +#define SGINT_TCWORD_CLAT 0x00 /* Latch command */ +#define SGINT_TCWORD_CLSB 0x10 /* LSB read/write */ +#define SGINT_TCWORD_CMSB 0x20 /* MSB read/write */ +#define SGINT_TCWORD_CALL 0x30 /* Full counter read/write */ +#define SGINT_TCWORD_CNT0 0x00 /* Select counter zero */ +#define SGINT_TCWORD_CNT1 0x40 /* Select counter one */ +#define SGINT_TCWORD_CNT2 0x80 /* Select counter two */ +#define SGINT_TCWORD_CRBCK 0xc0 /* Readback command */ + +#define SGINT_TCSAMP_COUNTER 0x164 + +struct sgi_int2_regs { + struct sgi_ioc_ints ints; + + volatile unsigned long ledbits; /* LED control bits */ +#define INT2_LED_TXCLK 0x01 /* GPI to TXCLK enable */ +#define INT2_LED_SERSLCT0 0x02 /* serial port0: 0=apple 1=pc */ +#define INT2_LED_SERSLCT1 0x04 /* serial port1: 0=apple 1=pc */ +#define INT2_LED_CHEAPER 0x08 /* 0=cheapernet 1=ethernet */ +#define INT2_LED_POWEROFF 0x10 /* Power-off request, active high */ + +#ifdef __MIPSEB__ + unsigned char _unused0[3]; + volatile unsigned char tclear; /* Timer clear strobe address */ +#else + volatile unsigned char tclear; /* Timer clear strobe address */ + unsigned char _unused0[3]; +#endif +#define INT2_TCLEAR_T0CLR 0x1 /* Clear timer0 IRQ */ +#define INT2_TCLEAR_T1CLR 0x2 /* Clear timer1 IRQ */ + + unsigned long _unused[3]; + struct sgi_ioc_timers timers; +}; + +struct sgi_int3_regs { + struct sgi_ioc_ints ints; + +#ifdef __MIPSEB__ + unsigned char _unused0[3]; + volatile unsigned char tclear; /* Timer clear strobe address */ +#else + volatile unsigned char tclear; /* Timer clear strobe address */ + unsigned char _unused0[3]; +#endif + volatile unsigned long estatus; /* Error status reg */ + unsigned long _unused1[2]; + struct sgi_ioc_timers timers; +}; + +extern struct sgi_int2_regs *sgi_i2regs; +extern struct sgi_int3_regs *sgi_i3regs; +extern struct sgi_ioc_ints *ioc_icontrol; +extern struct sgi_ioc_timers *ioc_timers; +extern volatile unsigned char *ioc_tclear; + +extern void sgint_init(void); +extern void indy_timer_init(void); + +#endif /* !(_MIPS_SGINT23_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/shmparam.h linux/include/asm-mips/shmparam.h --- v2.1.43/linux/include/asm-mips/shmparam.h Mon May 6 02:26:15 1996 +++ linux/include/asm-mips/shmparam.h Thu Jun 26 12:33:40 1997 @@ -39,7 +39,7 @@ #define SHMALL /* max shm system wide (pages) */ \ (1<<(_SHM_IDX_BITS+_SHM_ID_BITS)) /* - * This constant is very large but the ABI in its wisdom says ... + * 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 */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h --- v2.1.43/linux/include/asm-mips/sigcontext.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/sigcontext.h Thu Jun 26 12:33:40 1997 @@ -1,21 +1,50 @@ #ifndef __ASM_MIPS_SIGCONTEXT_H #define __ASM_MIPS_SIGCONTEXT_H +#ifdef __LANGUAGE_ASSEMBLY__ + +#define SC_REGMASK 0 +#define SC_STATUS 4 +#define SC_PC 8 +#define SC_REGS 16 +#define SC_FPREGS 272 +#define SC_OWNEDFP 528 +#define SC_FPC_CSR 532 +#define SC_FPC_EIR 536 +#define SC_SSFLAGS 540 +#define SC_MDHI 544 +#define SC_MDLO 552 + +#endif + +#if defined(__LANGUAGE_C__) || \ + defined(_LANGUAGE_C) || \ + defined(__LANGUAGE_C_PLUS_PLUS__) || \ + defined(__LANGUAGE_OBJECTIVE_C__) + /* - * 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 ... + * Whenever this structure is changed you must update the offsets in + * arch/mips/mips/fp-context.S. */ -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; +struct sigcontext { + unsigned int sc_regmask; /* Unused */ + unsigned int sc_status; + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; /* Unused */ + unsigned int sc_ownedfp; + unsigned int sc_fpc_csr; /* Unused */ + unsigned int sc_fpc_eir; /* Unused */ + unsigned int sc_ssflags; /* Unused */ + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; - unsigned long sc_epc; - unsigned long sc_cause; + unsigned int sc_cause; /* Unused */ + unsigned int sc_badvaddr; /* Unused */ - unsigned long sc_oldmask; + sigset_t sc_sigset; + unsigned long __pad0[3]; /* pad for constant size */ }; +#endif #endif /* __ASM_MIPS_SIGCONTEXT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h --- v2.1.43/linux/include/asm-mips/signal.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/signal.h Thu Jun 26 12:33:40 1997 @@ -1,26 +1,41 @@ -#ifndef __ASM_MIPS_SIGNAL_H -#define __ASM_MIPS_SIGNAL_H - /* - * For now ... + * Linux/MIPS specific definitions for signals. + * + * 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, 1996 by Ralf Baechle */ -#include -typedef __u64 sigset_t; +#ifndef __ASM_MIPS_SIGNAL_H -#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; +#include + +/* Any one of these symbols __need_* means that GNU libc + wants us just to define one data type. So don't define + the symbols that indicate this file's entire job has been done. */ +#if !defined(__need_signums) && !defined(__need_fake_sigfuns) && \ + !defined(__need__nsig) +#define __ASM_MIPS_SIGNAL_H #endif +#ifdef __ASM_MIPS_SIGNAL_H +typedef unsigned long sigset_t; +#endif /* __ASM_MIPS_SIGNAL_H */ + +#if !defined (___nsig_defined) && \ + (defined (__ASM_MIPS_SIGNAL_H) || defined (__need__nsig)) +#define ___nsig_defined #define _NSIG 65 +#endif +#undef __need__nsig +#ifdef __KERNEL__ #define NSIG _NSIG +#endif +#if !defined (__signums_defined) && \ + (defined (__ASM_MIPS_SIGNAL_H) || defined (__need_signums)) +#define __signums_defined /* * For 1.3.0 Linux/MIPS changed the signal numbers to be compatible the ABI. */ @@ -58,7 +73,10 @@ #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). */ +#endif /* need signums */ +#undef __need_signums +#ifdef __ASM_MIPS_SIGNAL_H /* * 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 @@ -87,37 +105,46 @@ */ #define SA_PROBE SA_ONESHOT #define SA_SAMPLE_RANDOM SA_RESTART -#endif +#endif /* __KERNEL__ */ -#define SIG_BLOCK 1 /* for blocking signals */ -#define SIG_UNBLOCK 2 /* for unblocking signals */ -#define SIG_SETMASK 3 /* for setting the signal mask */ +#define SIG_BLOCK 1 /* for blocking signals */ +#define SIG_UNBLOCK 2 /* for unblocking signals */ +#define SIG_SETMASK 3 /* for setting the signal mask */ +#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility: + set only the low 32 bit of the sigset. */ +#ifndef __sighandler_t_defined +#define __sighandler_t_defined /* Type of a signal handler. */ typedef void (*__sighandler_t)(int); +#endif +#endif +#if !defined (__fake_sigfuns_defined) && \ + (defined (__ASM_MIPS_SIGNAL_H) || defined (__need_fake_sigfuns)) +#define __fake_sigfuns_defined /* 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 */ +#endif +#undef __need_fake_sigfuns +#ifdef __ASM_MIPS_SIGNAL_H 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]; + unsigned int __pad0[3]; /* reserved, keep size constant */ /* Abi says here follows reserved int[2] */ void (*sa_restorer)(void); -#if __mips < 3 +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) /* * For 32 bit code we have to pad struct sigaction to get * constant size for the ABI */ - int pad0[1]; /* reserved */ + int __pad1[1]; /* reserved */ #endif }; @@ -125,4 +152,27 @@ #include #endif -#endif /* __ASM_MIPS_SIGNAL_H */ +#if defined (__KERNEL__) || defined (__USE_MISC) +/* + * The following break codes are or were in use for specific purposes in + * other MIPS operating systems. Linux/MIPS doesn't use all of them. The + * unused ones are here as placeholders; we might encounter them in + * non-Linux/MIPS object files or make use of them in the future. + */ +#define BRK_USERBP 0 /* User bp (used by debuggers) */ +#define BRK_KERNELBP 1 /* Break in the kernel */ +#define BRK_ABORT 2 /* Sometimes used by abort(3) to SIGIOT */ +#define BRK_BD_TAKEN 3 /* For bd slot emulation - not implemented */ +#define BRK_BD_NOTTAKEN 4 /* For bd slot emulation - not implemented */ +#define BRK_SSTEPBP 5 /* User bp (used by debuggers) */ +#define BRK_OVERFLOW 6 /* Overflow check */ +#define BRK_DIVZERO 7 /* Divide by zero check */ +#define BRK_RANGE 8 /* Range error check */ +#define BRK_STACKOVERFLOW 9 /* For Ada stackchecking */ +#define BRK_NORLD 10 /* No rld found - not used by Linux/MIPS */ +#define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ +#define BRK_MULOVF 1023 /* Multiply overflow */ +#endif /* defined (__KERNEL__) || defined (__USE_MISC) */ +#endif /* defined (__ASM_MIPS_SIGNAL_H) */ + +#endif /* !defined (__ASM_MIPS_SIGNAL_H) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/slots.h linux/include/asm-mips/slots.h --- v2.1.43/linux/include/asm-mips/slots.h Fri Jan 13 10:37:41 1995 +++ linux/include/asm-mips/slots.h Wed Dec 31 16:00:00 1969 @@ -1,17 +0,0 @@ -/* - * include/asm-mips/slots.h - * - * Copyright (C) 1994 by Waldorf Electronics - * Written by Ralf Baechle - */ -#ifndef __ASM_MIPS_SLOTS_H -#define __ASM_MIPS_SLOTS_H - -/* - * SLOTSPACE is the address to which the physical address 0 - * of the Slotspace is mapped by the chipset in the main CPU's - * address space. - */ -#define SLOTSPACE 0xe1000000 - -#endif /* __ASM_MIPS_SLOTS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/smp.h linux/include/asm-mips/smp.h --- v2.1.43/linux/include/asm-mips/smp.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/smp.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,6 @@ +#ifndef __ASM_MIPS_SMP_H +#define __ASM_MIPS_SMP_H + +/* We'll get here eventually.. */ + +#endif /* __ASM_MIPS_SMP_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/smp_lock.h linux/include/asm-mips/smp_lock.h --- v2.1.43/linux/include/asm-mips/smp_lock.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/smp_lock.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,26 @@ +/* + * 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) 1996 Ralf Baechle + * + * Linux/MIPS SMP support. Just a dummy to make building possible. + */ +#ifndef __ASM_MIPS_SMPLOCK_H +#define __ASM_MIPS_SMPLOCK_H + +#ifndef __SMP__ + +#define lock_kernel() do { } while(0) +#define unlock_kernel() do { } while(0) +#define release_kernel_lock(task, cpu, depth) ((depth) = 1) +#define reacquire_kernel_lock(task, cpu, depth) do { } while(0) + +#else + +#error "We do not support SMP on MIPS yet" + +#endif /* __SMP__ */ + +#endif /* __ASM_MIPS_SMPLOCK_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sni.h linux/include/asm-mips/sni.h --- v2.1.43/linux/include/asm-mips/sni.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sni.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,91 @@ +/* + * SNI specific 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) 1997 by Ralf Baechle + */ +#ifndef __ASM_MIPS_SNI_H +#define __ASM_MIPS_SNI_H + +#define SNI_PORT_BASE 0xb4000000 + +/* + * ASIC PCI registers for little endian configuration. + */ +#ifndef __MIPSEL__ +#error "Fix me for big endian" +#endif +#define PCIMT_UCONF 0xbfff0000 +#define PCIMT_IOADTIMEOUT2 0xbfff0008 +#define PCIMT_IOMEMCONF 0xbfff0010 +#define PCIMT_IOMMU 0xbfff0018 +#define PCIMT_IOADTIMEOUT1 0xbfff0020 +#define PCIMT_DMAACCESS 0xbfff0028 +#define PCIMT_DMAHIT 0xbfff0030 +#define PCIMT_ERRSTATUS 0xbfff0038 +#define PCIMT_ERRADDR 0xbfff0040 +#define PCIMT_SYNDROME 0xbfff0048 +#define PCIMT_ITPEND 0xbfff0050 +#define PCIMT_IRQSEL 0xbfff0058 +#define PCIMT_TESTMEM 0xbfff0060 +#define PCIMT_ECCREG 0xbfff0068 +#define PCIMT_CONFIG_ADDRESS 0xbfff0070 +#define PCIMT_ASIC_ID 0xbfff0078 /* read */ +#define PCIMT_SOFT_RESET 0xbfff0078 /* write */ +#define PCIMT_PIA_OE 0xbfff0080 +#define PCIMT_PIA_DATAOUT 0xbfff0088 +#define PCIMT_PIA_DATAIN 0xbfff0090 +#define PCIMT_CACHECONF 0xbfff0098 +#define PCIMT_INVSPACE 0xbfff00a0 +#define PCIMT_PCI_CONF 0xbfff0100 + +/* + * Data port for the PCI bus. + */ +#define PCIMT_CONFIG_DATA 0xb4000cfc + +/* + * Board specific registers + */ +#define PCIMT_CSMSR 0xbfd00000 +#define PCIMT_CSSWITCH 0xbfd10000 +#define PCIMT_CSITPEND 0xbfd20000 +#define PCIMT_AUTO_PO_EN 0xbfd30000 +#define PCIMT_CLR_TEMP 0xbfd40000 +#define PCIMT_AUTO_PO_DIS 0xbfd50000 +#define PCIMT_EXMSR 0xbfd60000 +#define PCIMT_UNUSED1 0xbfd70000 +#define PCIMT_CSWCSM 0xbfd80000 +#define PCIMT_UNUSED2 0xbfd90000 +#define PCIMT_CSLED 0xbfda0000 +#define PCIMT_CSMAPISA 0xbfdb0000 +#define PCIMT_CSRSTBP 0xbfdc0000 +#define PCIMT_CLRPOFF 0xbfdd0000 +#define PCIMT_CSTIMER 0xbfde0000 +#define PCIMT_PWDN 0xbfdf0000 + +/* + * Interrupt 0-16 are reserved for PCI and EISA interrupts. The + * interrupts from 16 are assigned to the other interrupts generated + * by the PCI chipset. + */ +#define PCIMT_IRQ_ETHERNET 16 +#define PCIMT_IRQ_TEMPERATURE 17 +#define PCIMT_IRQ_EISA_NMI 18 +#define PCIMT_IRQ_POWER_OFF 19 +#define PCIMT_IRQ_BUTTON 20 +#define PCIMT_IRQ_INTA 21 +#define PCIMT_IRQ_INTB 22 +#define PCIMT_IRQ_INTC 23 +#define PCIMT_IRQ_INTD 24 +#define PCIMT_IRQ_SCSI 25 + +/* + * Base address for the mapped 16mb EISA bus segment. + */ +#define PCIMT_EISA_BASE 0xb0000000 + +#endif /* __ASM_MIPS_SNI_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h --- v2.1.43/linux/include/asm-mips/socket.h Thu Mar 27 14:40:07 1997 +++ linux/include/asm-mips/socket.h Thu Jun 26 12:33:40 1997 @@ -2,17 +2,7 @@ #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 */ +#include /* * For setsockoptions(2) @@ -21,43 +11,57 @@ */ #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 +#define SO_DEBUG 0x0001 /* Record debugging information. */ +#define SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ +#define SO_KEEPALIVE 0x0008 /* Keep connections alive and send + SIGPIPE when they die. */ +#define SO_DONTROUTE 0x0010 /* Don't do local routing. */ +#define SO_BROADCAST 0x0020 /* Allow transmission of + broadcast messages. */ +#define SO_LINGER 0x0080 /* Block on close of a reliable + socket to transmit pending data. */ +#define SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ +#if 0 +To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ +#endif + +#define SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ +#define SO_STYLE SO_TYPE /* Synonym */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_SNDBUF 0x1001 /* Send buffer size. */ +#define SO_RCVBUF 0x1002 /* Receive buffer. */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ /* linux-specific, might as well be the same as on i386 */ #define SO_NO_CHECK 11 #define SO_PRIORITY 12 #define SO_BSDCOMPAT 14 -/* - * Weird. 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. */ +#define SO_PASSCRED 17 +#define SO_PEERCRED 18 /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 22 #define SO_SECURITY_ENCRYPTION_TRANSPORT 23 #define SO_SECURITY_ENCRYPTION_NETWORK 24 + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_DGRAM = 1, /* Connectionless, unreliable datagrams + of fixed maximum length. */ + SOCK_STREAM = 2, /* Sequenced, reliable, connection-based + byte streams. */ + SOCK_RAW = 3, /* Raw protocol interface. */ + SOCK_RDM = 4, /* Reliably-delivered messages. */ + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ + 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 v2.1.43/linux/include/asm-mips/sockios.h linux/include/asm-mips/sockios.h --- v2.1.43/linux/include/asm-mips/sockios.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/sockios.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,25 @@ +/* + * Socket-level I/O control calls. + * + * 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_SOCKIOS_H +#define __ASM_MIPS_SOCKIOS_H + +#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 */ + +#endif /* __ASM_MIPS_SOCKIOS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h --- v2.1.43/linux/include/asm-mips/softirq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/softirq.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,93 @@ +#ifndef __ASM_MIPS_SOFTIRQ_H +#define __ASM_MIPS_SOFTIRQ_H + +/* The locking mechanism for base handlers, to prevent re-entrancy, + * is entirely private to an implementation, it should not be + * referenced at all outside of this file. + */ +extern atomic_t __mips_bh_counter; + +#define get_active_bhs() (bh_mask & bh_active) + +static inline void clear_active_bhs(unsigned long x) +{ + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0,%1\n\t" + "and\t%0,%2\n\t" + "sc\t%0,%1\n\t" + "beqz\t%0,1b" + :"=&r" (temp), + "=m" (bh_active) + :"Ir" (x), + "m" (bh_active)); +} + +extern inline void init_bh(int nr, void (*routine)(void)) +{ + bh_base[nr] = routine; + bh_mask_count[nr] = 0; + bh_mask |= 1 << nr; +} + +extern inline void remove_bh(int nr) +{ + bh_base[nr] = NULL; + bh_mask &= ~(1 << nr); +} + +extern inline void mark_bh(int nr) +{ + set_bit(nr, &bh_active); +} + +/* + * These use a mask count to correctly handle + * nested disable/enable calls + */ +extern inline void disable_bh(int nr) +{ + bh_mask &= ~(1 << nr); + bh_mask_count[nr]++; +} + +extern inline void enable_bh(int nr) +{ + if (!--bh_mask_count[nr]) + bh_mask |= 1 << nr; +} + +/* + * start_bh_atomic/end_bh_atomic also nest + * naturally by using a counter + */ +extern inline void start_bh_atomic(void) +{ +#ifdef __SMP__ + atomic_inc(&__mips_bh_counter); + synchronize_irq(); +#else + atomic_inc(&__mips_bh_counter); +#endif +} + +extern inline void end_bh_atomic(void) +{ + atomic_dec(&__mips_bh_counter); +} + +#ifndef __SMP__ + +/* These are for the irq's testing the lock */ +#define softirq_trylock() (atomic_read(&__mips_bh_counter) ? \ + 0 : \ + ((atomic_set(&__mips_bh_counter,1)),1)) +#define softirq_endlock() (atomic_set(&__mips_bh_counter, 0)) + +#else + +#error FIXME + +#endif /* __SMP__ */ +#endif /* __ASM_MIPS_SOFTIRQ_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/spinlock.h linux/include/asm-mips/spinlock.h --- v2.1.43/linux/include/asm-mips/spinlock.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/spinlock.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,54 @@ +#ifndef __ASM_MIPS_SPINLOCK_H +#define __ASM_MIPS_SPINLOCK_H + +#ifndef __SMP__ + +/* gcc 2.7.2 can crash initializing an empty structure. For now we + try to do though ... */ +typedef struct { } spinlock_t; +#define SPIN_LOCK_UNLOCKED { } + +#define spin_lock_init(lock) do { } while(0) +#define spin_lock(lock) do { } while(0) +#define spin_trylock(lock) do { } while(0) +#define spin_unlock_wait(lock) do { } while(0) +#define spin_unlock(lock) do { } while(0) +#define spin_lock_irq(lock) cli() +#define spin_unlock_irq(lock) sti() + +#define spin_lock_irqsave(lock, flags) save_and_cli(flags) +#define spin_unlock_irqrestore(lock, flags) restore_flags(flags) + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ +typedef struct { } rwlock_t; +#define RW_LOCK_UNLOCKED { } + +#define read_lock(lock) do { } while(0) +#define read_unlock(lock) do { } while(0) +#define write_lock(lock) do { } while(0) +#define write_unlock(lock) do { } while(0) +#define read_lock_irq(lock) cli() +#define read_unlock_irq(lock) sti() +#define write_lock_irq(lock) cli() +#define write_unlock_irq(lock) sti() + +#define read_lock_irqsave(lock, flags) save_and_cli(flags) +#define read_unlock_irqrestore(lock, flags) restore_flags(flags) +#define write_lock_irqsave(lock, flags) save_and_cli(flags) +#define write_unlock_irqrestore(lock, flags) restore_flags(flags) + +#else + +#error "Nix SMP on MIPS" + +#endif /* SMP */ +#endif /* __ASM_MIPS_SPINLOCK_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h --- v2.1.43/linux/include/asm-mips/stackframe.h Wed Dec 13 02:39:46 1995 +++ linux/include/asm-mips/stackframe.h Thu Jun 26 12:33:40 1997 @@ -1,189 +1,139 @@ /* * include/asm-mips/stackframe.h * - * Copyright (C) 1994, 1995 Waldorf Electronics - * written by Ralf Baechle + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine. */ - #ifndef __ASM_MIPS_STACKFRAME_H #define __ASM_MIPS_STACKFRAME_H -/* - * 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 include/asm-mips/ptrace.h - * - * The first PTRSIZE*5 bytes are argument save space for C subroutines. - */ -#define FR_REG1 (PTRSIZE*5) -#define FR_REG2 ((FR_REG1) + 4) -#define FR_REG3 ((FR_REG2) + 4) -#define FR_REG4 ((FR_REG3) + 4) -#define FR_REG5 ((FR_REG4) + 4) -#define FR_REG6 ((FR_REG5) + 4) -#define FR_REG7 ((FR_REG6) + 4) -#define FR_REG8 ((FR_REG7) + 4) -#define FR_REG9 ((FR_REG8) + 4) -#define FR_REG10 ((FR_REG9) + 4) -#define FR_REG11 ((FR_REG10) + 4) -#define FR_REG12 ((FR_REG11) + 4) -#define FR_REG13 ((FR_REG12) + 4) -#define FR_REG14 ((FR_REG13) + 4) -#define FR_REG15 ((FR_REG14) + 4) -#define FR_REG16 ((FR_REG15) + 4) -#define FR_REG17 ((FR_REG16) + 4) -#define FR_REG18 ((FR_REG17) + 4) -#define FR_REG19 ((FR_REG18) + 4) -#define FR_REG20 ((FR_REG19) + 4) -#define FR_REG21 ((FR_REG20) + 4) -#define FR_REG22 ((FR_REG21) + 4) -#define FR_REG23 ((FR_REG22) + 4) -#define FR_REG24 ((FR_REG23) + 4) -#define FR_REG25 ((FR_REG24) + 4) +#include +#include -/* - * $26 (k0) and $27 (k1) not saved - */ -#define FR_REG28 ((FR_REG25) + 4) -#define FR_REG29 ((FR_REG28) + 4) -#define FR_REG30 ((FR_REG29) + 4) -#define FR_REG31 ((FR_REG30) + 4) - -/* - * Saved special registers - */ -#define FR_LO ((FR_REG31) + 4) -#define FR_HI ((FR_LO) + 4) - -/* - * Saved cp0 registers follow - */ -#define FR_STATUS ((FR_HI) + 4) -#define FR_EPC ((FR_STATUS) + 4) -#define FR_CAUSE ((FR_EPC) + 4) +#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, PT_SIZE; \ + sw k0, PT_R29(sp); \ + sw $2, PT_R2(sp); \ + sw $1, PT_R1(sp); \ + sw $2, PT_OR2(sp); \ + sw $0, PT_R0(sp); \ + mfc0 v0, CP0_STATUS; \ + sw $3, PT_R3(sp); \ + sw v0, PT_STATUS(sp); \ + sw $4, PT_R4(sp); \ + mfc0 v0, CP0_CAUSE; \ + sw $5, PT_R5(sp); \ + sw v0, PT_CAUSE(sp); \ + sw $6, PT_R6(sp); \ + mfc0 v0, CP0_EPC; \ + sw $7, PT_R7(sp); \ + sw v0, PT_EPC(sp); \ + sw $7, PT_OR7(sp); \ + sw $8, PT_R8(sp); \ + mfhi v0; \ + sw $9, PT_R9(sp); \ + sw v0, PT_HI(sp); \ + sw $10,PT_R10(sp); \ + mflo v0; \ + sw $11, PT_R11(sp); \ + sw v0, PT_LO(sp); \ + sw $12, PT_R12(sp); \ + sw $13, PT_R13(sp); \ + sw $14, PT_R14(sp); \ + sw $15, PT_R15(sp); \ + sw $16, PT_R16(sp); \ + sw $17, PT_R17(sp); \ + sw $18, PT_R18(sp); \ + sw $19, PT_R19(sp); \ + sw $20, PT_R20(sp); \ + sw $21, PT_R21(sp); \ + sw $22, PT_R22(sp); \ + sw $23, PT_R23(sp); \ + sw $24, PT_R24(sp); \ + sw $25, PT_R25(sp); \ + sw $28, PT_R28(sp); \ + sw $30, PT_R30(sp); \ + sw $31, PT_R31(sp); /* - * Some goodies... + * Note that we restore the IE flags from stack. This means + * that a modified IE mask will be nullified. */ -#define FR_INTERRUPT ((FR_CAUSE) + 4) -#define FR_ORIG_REG2 ((FR_INTERRUPT) + 4) -#define FR_PAD1 ((FR_ORIG_REG2) + 4) +#define RESTORE_ALL \ + mfc0 t0, CP0_STATUS; \ + ori t0, 0x1f; \ + xori t0, 0x1f; \ + mtc0 t0, CP0_STATUS; \ + lw v0, PT_STATUS(sp); \ + lw v1, PT_LO(sp); \ + mtc0 v0, CP0_STATUS; \ + mtlo v1; \ + lw v0, PT_HI(sp); \ + lw v1, PT_EPC(sp); \ + mthi v0; \ + mtc0 v1, CP0_EPC; \ + lw $31, PT_R31(sp); \ + lw $30, PT_R30(sp); \ + lw $28, PT_R28(sp); \ + lw $25, PT_R25(sp); \ + lw $24, PT_R24(sp); \ + lw $23, PT_R23(sp); \ + lw $22, PT_R22(sp); \ + lw $21, PT_R21(sp); \ + lw $20, PT_R20(sp); \ + lw $19, PT_R19(sp); \ + lw $18, PT_R18(sp); \ + lw $17, PT_R17(sp); \ + lw $16, PT_R16(sp); \ + lw $15, PT_R15(sp); \ + lw $14, PT_R14(sp); \ + lw $13, PT_R13(sp); \ + lw $12, PT_R12(sp); \ + lw $11, PT_R11(sp); \ + lw $10, PT_R10(sp); \ + lw $9, PT_R9(sp); \ + lw $8, PT_R8(sp); \ + lw $7, PT_R7(sp); \ + lw $6, PT_R6(sp); \ + lw $5, PT_R5(sp); \ + lw $4, PT_R4(sp); \ + lw $3, PT_R3(sp); \ + lw $2, PT_R2(sp); \ + lw $1, PT_R1(sp); \ + lw sp, PT_R29(sp); /* - * Size of stack frame, word/double word alignment + * Move to kernel mode and disable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack */ -#define FR_SIZE ((((FR_PAD1) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1)) - -#ifdef __R4000__ - -#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) +#define CLI \ + mfc0 t0,CP0_STATUS; \ + li t1,ST0_CU0|0x1f; \ + or t0,t1; \ + xori t0,0x1f; \ + mtc0 t0,CP0_STATUS /* - * Note that we restore the IE flags from stack. This means - * that a modified IE mask will be nullified. + * Move to kernel mode and enable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack + * + * 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/mips3/r4xx0.S makes use of this fact. */ -#define RESTORE_ALL \ - .set mips3; \ +#define STI \ 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 - -#else /* !defined (__R4000__) */ - -#error "Implement SAVE_ALL and RESTORE_ALL!" - -#endif /* !defined (__R4000__) */ + li t1,ST0_CU0|0x1f; \ + or t0,t1; \ + xori t0,0x1e; \ + mtc0 t0,CP0_STATUS #endif /* __ASM_MIPS_STACKFRAME_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/stat.h linux/include/asm-mips/stat.h --- v2.1.43/linux/include/asm-mips/stat.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/stat.h Thu Jun 26 12:33:40 1997 @@ -3,7 +3,7 @@ #include -struct old_stat { +struct __old_kernel_stat { unsigned int st_dev; unsigned int st_ino; unsigned int st_mode; @@ -21,7 +21,7 @@ unsigned int st_gen; }; -struct new_stat { +struct stat { dev_t st_dev; long st_pad1[3]; /* Reserved for network id */ ino_t st_ino; diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/statfs.h linux/include/asm-mips/statfs.h --- v2.1.43/linux/include/asm-mips/statfs.h Wed Dec 13 02:39:47 1995 +++ linux/include/asm-mips/statfs.h Thu Jun 26 12:33:40 1997 @@ -1,25 +1,40 @@ +/* + * Definitions for the statfs(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_STATFS_H #define __ASM_MIPS_STATFS_H -typedef struct { - long val[2]; -} fsid_t; +#include + +#ifndef __KERNEL_STRICT_NAMES + +#include + +typedef __kernel_fsid_t fsid_t; + +#endif struct statfs { - long f_type; + 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; + 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]; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; }; #endif /* __ASM_MIPS_STATFS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/string.h linux/include/asm-mips/string.h --- v2.1.43/linux/include/asm-mips/string.h Wed Dec 13 02:39:47 1995 +++ linux/include/asm-mips/string.h Thu Jun 26 12:33:40 1997 @@ -5,16 +5,15 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1994, 1995 Waldorf Electronics - * written by Ralf Baechle + * Copyright (c) 1994, 1995, 1996 by Ralf Baechle */ #ifndef __ASM_MIPS_STRING_H #define __ASM_MIPS_STRING_H #define __HAVE_ARCH_STRCPY -extern __inline__ char * strcpy(char * dest, const char *src) +extern __inline__ char *strcpy(char *__dest, __const__ char *__src) { - char *xdest = dest; + char *__xdest = __dest; __asm__ __volatile__( ".set\tnoreorder\n\t" @@ -26,43 +25,43 @@ "addiu\t%0,1\n\t" ".set\tat\n\t" ".set\treorder" - : "=r" (dest), "=r" (src) - : "0" (dest), "1" (src) + : "=r" (__dest), "=r" (__src) + : "0" (__dest), "1" (__src) : "$1","memory"); - return xdest; + return __xdest; } #define __HAVE_ARCH_STRNCPY -extern __inline__ char * strncpy(char *dest, const char *src, size_t n) +extern __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) { - char *xdest = dest; + char *__xdest = __dest; - if (n == 0) - return xdest; + if (__n == 0) + return __xdest; __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n" "1:\tlbu\t$1,(%1)\n\t" - "subu\t%2,%2,1\n\t" + "subu\t%2,1\n\t" "sb\t$1,(%0)\n\t" "beqz\t$1,2f\n\t" - "addiu\t%0,%0,1\n\t" + "addiu\t%0,1\n\t" "bnez\t%2,1b\n\t" - "addiu\t%1,%1,1\n" + "addiu\t%1,1\n" "2:\n\t" ".set\tat\n\t" - ".set\treorder\n\t" - : "=r" (dest), "=r" (src), "=r" (n) - : "0" (dest), "1" (src), "2" (n) + ".set\treorder" + : "=r" (__dest), "=r" (__src), "=r" (__n) + : "0" (__dest), "1" (__src), "2" (__n) : "$1","memory"); - return dest; + return __dest; } #define __HAVE_ARCH_STRCMP -extern __inline__ int strcmp(const char * cs, const char * ct) +extern __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct) { int __res; @@ -76,22 +75,22 @@ "addiu\t%1,1\n\t" "bnez\t%2,1b\n\t" "lbu\t%2,(%0)\n\t" -#ifndef __R4000__ +#if _MIPS_ISA == _MIPS_ISA_MIPS1 "nop\n\t" #endif "move\t%2,$1\n" "2:\tsubu\t%2,$1\n" "3:\t.set\tat\n\t" ".set\treorder" - : "=d" (cs), "=d" (ct), "=d" (__res) - : "0" (cs), "1" (ct) + : "=r" (__cs), "=r" (__ct), "=r" (__res) + : "0" (__cs), "1" (__ct) : "$1"); return __res; } #define __HAVE_ARCH_STRNCMP -extern __inline__ int strncmp(const char * cs, const char * ct, size_t count) +extern __inline__ int strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count) { char __res; @@ -110,118 +109,50 @@ "3:\tsubu\t%3,$1\n\t" ".set\tat\n\t" ".set\treorder" - : "=d" (cs), "=d" (ct), "=d" (count), "=d" (__res) - : "0" (cs), "1" (ct), "2" (count) + : "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res) + : "0" (__cs), "1" (__ct), "2" (__count) : "$1"); return __res; } #define __HAVE_ARCH_MEMSET -extern __inline__ void * memset(void * s, int c, size_t count) -{ - void *xs = s; - - if (!count) - return xs; - __asm__ __volatile__( - ".set\tnoreorder\n" - "1:\tsb\t%3,(%0)\n\t" - "bne\t%0,%1,1b\n\t" - "addiu\t%0,%0,1\n\t" - ".set\treorder" - : "=r" (s), "=r" (count) - : "0" (s), "r" (c), "1" (s + count - 1) - : "memory"); - - return xs; -} +extern void *memset(void *__s, char __c, size_t __count); #define __HAVE_ARCH_MEMCPY -extern __inline__ void * memcpy(void * to, const void * from, size_t n) -{ - void *xto = to; - - if (!n) - return xto; - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n" - "1:\tlbu\t$1,(%1)\n\t" - "addiu\t%1,1\n\t" - "sb\t$1,(%0)\n\t" - "subu\t%2,1\n\t" - "bnez\t%2,1b\n\t" - "addiu\t%0,1\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (to), "=r" (from), "=r" (n) - : "0" (to), "1" (from), "2" (n) - : "$1","memory" ); - return xto; -} +extern void *memcpy(void *__to, __const__ void *__from, size_t __n); #define __HAVE_ARCH_MEMMOVE -extern __inline__ void * memmove(void * dest,const void * src, size_t n) -{ - void *xdest = dest; - - if (!n) - return xdest; +extern void *memmove(void *__dest, __const__ void *__src, size_t __n); - if (dest < src) - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n" - "1:\tlbu\t$1,(%1)\n\t" - "addiu\t%1,1\n\t" - "sb\t$1,(%0)\n\t" - "subu\t%2,1\n\t" - "bnez\t%2,1b\n\t" - "addiu\t%0,1\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (dest), "=r" (src), "=r" (n) - : "0" (dest), "1" (src), "2" (n) - : "$1","memory" ); - else - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n" - "1:\tlbu\t$1,-1(%1)\n\t" - "subu\t%1,1\n\t" - "sb\t$1,-1(%0)\n\t" - "subu\t%2,1\n\t" - "bnez\t%2,1b\n\t" - "subu\t%0,1\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (dest), "=r" (src), "=r" (n) - : "0" (dest+n), "1" (src+n), "2" (n) - : "$1","memory" ); - return xdest; -} +#define __HAVE_ARCH_BCOPY +extern char * bcopy(const char * src, char * dest, int count); #define __HAVE_ARCH_MEMSCAN -extern __inline__ void * memscan(void * addr, int c, size_t size) +extern __inline__ void *memscan(void *__addr, int __c, size_t __size) { - if (!size) - return addr; + char *__end = (char *)__addr + __size; + + if (!__size) + return __addr; __asm__(".set\tnoreorder\n\t" ".set\tnoat\n" - "1:\tbeqz\t%1,2f\n\t" - "lbu\t$1,(%0)\n\t" - "subu\t%1,1\n\t" - "bnez\t%1,1b\n\t" + "1:\tlbu\t$1,(%0)\n\t" +#if _MIPS_ISA == _MIPS_ISA_MIPS1 + "nop\n\t" +#endif + "beq\t$1,%3,2f\n\t" "addiu\t%0,1\n\t" + "bne\t%0,%2,1b\n\t" + "nop\n\t" ".set\tat\n\t" ".set\treorder\n" "2:" - : "=r" (addr), "=r" (size) - : "0" (addr), "1" (size), "r" (c) + : "=r" (__addr) + : "0" (__addr), "1" (__end), "r" (__c) : "$1"); - return addr; + return __addr; } #endif /* __ASM_MIPS_STRING_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/sysmips.h linux/include/asm-mips/sysmips.h --- v2.1.43/linux/include/asm-mips/sysmips.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/sysmips.h Thu Jun 26 12:33:40 1997 @@ -19,6 +19,7 @@ #define SETNAME 1 /* set hostname */ #define FLUSH_CACHE 3 /* writeback and invalidate caches */ #define MIPS_FIXADE 7 /* control address error fixing */ +#define MIPS_RDNVRAM 10 /* read NVRAM */ #define MIPS_ATOMIC_SET 2001 /* atomically set variable */ #endif /* __ASM_MIPS_SYSMIPS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v2.1.43/linux/include/asm-mips/system.h Wed Dec 13 02:39:47 1995 +++ linux/include/asm-mips/system.h Thu Jun 26 12:33:40 1997 @@ -6,33 +6,73 @@ * for more details. * * Copyright (C) 1994, 1995 by Ralf Baechle + * Modified further for R[236]000 by Paul M. Antoine, 1996 */ #ifndef __ASM_MIPS_SYSTEM_H #define __ASM_MIPS_SYSTEM_H +#include #include -#if defined (__R4000__) -#define sti() \ +extern __inline__ void +__sti(void) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,0x1f\n\t" + "xori\t$1,0x1e\n\t" + "mtc0\t$1,$12\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); +} + +/* + * For cli() we have to insert nops to make shure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +extern __inline__ void +__cli(void) +{ + __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" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); +} + +#define __save_flags(x) \ __asm__ __volatile__( \ ".set\tnoreorder\n\t" \ - ".set\tnoat\n\t" \ - "mfc0\t$1,$12\n\t" \ - "ori\t$1,0x1f\n\t" \ - "xori\t$1,0x1e\n\t" \ - "mtc0\t$1,$12\n\t" \ - ".set\tat\n\t" \ + "mfc0\t%0,$12\n\t" \ ".set\treorder" \ - : /* no outputs */ \ + : "=r" (x) \ : /* no inputs */ \ - : "$1") + : "memory") -#define cli() \ +#define __save_and_cli(x) \ __asm__ __volatile__( \ ".set\tnoreorder\n\t" \ ".set\tnoat\n\t" \ - "mfc0\t$1,$12\n\t" \ - "ori\t$1,1\n\t" \ + "mfc0\t%0,$12\n\t" \ + "ori\t$1,%0,1\n\t" \ "xori\t$1,1\n\t" \ "mtc0\t$1,$12\n\t" \ "nop\n\t" \ @@ -40,78 +80,71 @@ "nop\n\t" \ ".set\tat\n\t" \ ".set\treorder" \ - : /* no outputs */ \ + : "=r" (x) \ : /* no inputs */ \ - : "$1") + : "$1", "memory") + +extern void __inline__ +__restore_flags(int flags) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "mtc0\t%0,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\treorder" + : /* no output */ + : "r" (flags) + : "memory"); +} -#else /* !defined (__R4000__) */ /* - * Untested goodies for the R3000 based DECstation et al. + * Non-SMP versions ... */ -#define sti() \ -__asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n\t" \ - "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") -#endif /* !defined (__R4000__) */ +#define sti() __sti() +#define cli() __cli() +#define save_flags(x) __save_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define restore_flags(x) __restore_flags(x) -#define nop() __asm__ __volatile__ ("nop") - -#define save_flags(x) \ +#define sync_mem() \ __asm__ __volatile__( \ ".set\tnoreorder\n\t" \ - "mfc0\t%0,$12\n\t" \ + "sync\n\t" \ ".set\treorder" \ - : "=r" (x)) \ + : /* no output */ \ + : /* no input */ \ + : "memory") -#define restore_flags(x) \ -__asm__ __volatile__( \ - ".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)) \ +#if !defined (__LANGUAGE_ASSEMBLY__) +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + */ +extern asmlinkage void (*resume)(void *tsk); +#endif /* !defined (__LANGUAGE_ASSEMBLY__) */ -#define sync_mem() \ -__asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - "sync\n\t" \ - ".set\treorder") \ +/* + * FIXME: resume() assumes current == prev + */ +#define switch_to(prev,next) \ +do { \ + prev->tss.current_ds = active_ds; \ + active_ds = next->tss.current_ds; \ + resume(next); \ +} while(0) /* * 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) +extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val) { unsigned long flags, retval; save_flags(flags); - sti(); + cli(); retval = *m; *m = val; restore_flags(flags); @@ -119,12 +152,12 @@ return retval; } -extern inline unsigned long xchg_u16(volatile short * m, unsigned long val) +extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val) { unsigned long flags, retval; save_flags(flags); - sti(); + cli(); retval = *m; *m = val; restore_flags(flags); @@ -136,8 +169,10 @@ * For 32 and 64 bit operands we can take advantage of ll and sc. * FIXME: This doesn't work for R3000 machines. */ -extern inline unsigned long xchg_u32(volatile int * m, unsigned long val) +extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) { +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) unsigned long dummy; __asm__ __volatile__( @@ -152,14 +187,23 @@ ".set\treorder" : "=r" (val), "=r" (m), "=r" (dummy) : "1" (m), "2" (val)); +#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */ + unsigned long flags, retval; + + save_flags(flags); + cli(); + retval = *m; + *m = val; + restore_flags(flags); +#endif /* Processor-dependent optimization */ return val; } /* * Only used for 64 bit kernel. */ -extern inline unsigned long xchg_u64(volatile long * m, unsigned long val) +extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val) { unsigned long dummy; @@ -192,7 +236,7 @@ */ extern void __xchg_called_with_bad_pointer(void); -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { case 1: diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/termbits.h linux/include/asm-mips/termbits.h --- v2.1.43/linux/include/asm-mips/termbits.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/termbits.h Thu Jun 26 12:33:40 1997 @@ -1,25 +1,26 @@ +/* + * termbits stuff for Linux/MIPS. + * + * 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, 1996 by Ralf Baechle + */ #ifndef __ASM_MIPS_TERMBITS_H #define __ASM_MIPS_TERMBITS_H -#include -#include +#include + +typedef unsigned char cc_t; +typedef unsigned long speed_t; +typedef unsigned long tcflag_t; /* * 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 */ @@ -31,5 +32,175 @@ cc_t c_line; /* line discipline */ cc_t c_cc[NCCS]; /* control characters */ }; + +/* 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 VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ +#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ +#define VEOL2 6 /* Second EOL character [ICANON]. */ +#define VSWTC 7 /* ??? */ +#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 + */ +#define VDSUSP 11 /* Delayed suspend character [ISIG]. */ +#endif +#define VREPRINT 12 /* Reprint-line character [ICANON]. */ +#define VDISCARD 13 /* Discard character [IEXTEN]. */ +#define VWERASE 14 /* Word-erase character [ICANON]. */ +#define VLNEXT 15 /* Literal-next character [IEXTEN]. */ +#define VEOF 16 /* End-of-file character [ICANON]. */ +#define VEOL 17 /* End-of-line character [ICANON]. */ + +/* 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 B460800 0010004 +#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CISPAR 010000000000 /* mark or space (stick) parity */ +#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 + +/* 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. */ #endif /* __ASM_MIPS_TERMBITS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h --- v2.1.43/linux/include/asm-mips/termios.h Mon Dec 30 02:56:38 1996 +++ linux/include/asm-mips/termios.h Thu Jun 26 12:33:40 1997 @@ -1,8 +1,45 @@ +/* + * ioctls for Linux/MIPS. + * + * 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, 1996 by Ralf Baechle + */ #ifndef __ASM_MIPS_TERMIOS_H -#define __ASM_MIPS_TERMIOS_H -#include #include +#include + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + int sg_flags; /* SGI special - int, not short */ +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; /* stop process signal */ + char t_dsuspc; /* delayed stop process signal */ + char t_rprntc; /* reprint line */ + char t_flushc; /* flush output (toggles) */ + char t_werasc; /* word erase */ + char t_lnextc; /* literal next character */ +}; + +/* TIOCGSIZE, TIOCSSIZE not defined yet. Only needed for SunOS source + compatibility anyway ... */ struct winsize { unsigned short ws_row; @@ -11,15 +48,60 @@ unsigned short ws_ypixel; }; -/* ----------------------------------------------------------------------- */ +#define NCC 8 +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 */ +}; + +#ifdef __KERNEL__ +/* + * intr=^C quit=^\ erase=del kill=^U + * vmin=\1 vtime=\0 eol2=\0 swtc=\0 + * start=^Q stop=^S susp=^Z vdsusp= + * reprint=^R discard=^U werase=^W lnext=^V + * eof=^D eol=\0 + */ +#define INIT_C_CC "\003\034\177\025\1\0\0\0\021\023\032\0\022\017\027\026\004\0" +#endif + +/* 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 */ +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ #ifdef __KERNEL__ +#include + /* * Translate a "termio" structure into a "termios". Ugh. */ #define user_termio_to_kernel_termios(termios, termio) \ -do { \ +({ \ unsigned short tmp; \ get_user(tmp, &(termio)->c_iflag); \ (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \ @@ -31,24 +113,24 @@ (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \ get_user((termios)->c_line, &(termio)->c_line); \ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -} while(0) +}) /* * Translate a "termios" structure into a "termio". Ugh. */ #define kernel_termios_to_user_termio(termio, termios) \ -do { \ +({ \ put_user((termios)->c_iflag, &(termio)->c_iflag); \ put_user((termios)->c_oflag, &(termio)->c_oflag); \ put_user((termios)->c_cflag, &(termio)->c_cflag); \ put_user((termios)->c_lflag, &(termio)->c_lflag); \ put_user((termios)->c_line, &(termio)->c_line); \ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -} while(0) +}) #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) -#endif /* __KERNEL__ */ +#endif /* defined(__KERNEL__) */ #endif /* __ASM_MIPS_TERMIOS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/types.h linux/include/asm-mips/types.h --- v2.1.43/linux/include/asm-mips/types.h Wed Dec 13 02:39:47 1995 +++ linux/include/asm-mips/types.h Thu Jun 26 12:33:40 1997 @@ -5,36 +5,12 @@ * 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 + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle */ #ifndef __ASM_MIPS_TYPES_H #define __ASM_MIPS_TYPES_H -#ifndef _SIZE_T -#define _SIZE_T -typedef __SIZE_TYPE__ size_t; -#endif - -#ifndef _SSIZE_T -#define _SSIZE_T -typedef __SSIZE_TYPE__ ssize_t; -#endif - -#ifndef _PTRDIFF_T -#define _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 +typedef unsigned long umode_t; /* * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the @@ -93,66 +69,5 @@ #endif #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; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#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 v2.1.43/linux/include/asm-mips/uaccess.h linux/include/asm-mips/uaccess.h --- v2.1.43/linux/include/asm-mips/uaccess.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/uaccess.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,352 @@ +/* + * include/asm-mips/uaccess.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) 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_UACCESS_H +#define __ASM_MIPS_UACCESS_H + +#include +#include +#include + +#define STR(x) __STR(x) +#define __STR(x) #x + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + */ +#define KERNEL_DS 0 +#define USER_DS 1 + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +extern int active_ds; + +#define get_fs() active_ds +#define set_fs(x) (active_ds=(x)) + +static inline unsigned long get_ds(void) +{ + return KERNEL_DS; +} + +/* + * Is a address valid? This does a straighforward calculation rather + * than tests. + * + * Address valid if: + * - "addr" doesn't have any high-bits set + * - AND "size" doesn't have any high-bits set + * - AND "addr+size" doesn't have any high-bits set + * - OR we are in kernel mode. + */ +#define __access_ok(addr,size,mask) \ + (((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0) +#define __access_mask (-(long)get_fs()) + +#define access_ok(type,addr,size) \ +__access_ok(((unsigned long)(addr)),(size),__access_mask) + +extern inline int verify_area(int type, const void * addr, unsigned long size) +{ + return access_ok(type,addr,size) ? 0 : -EFAULT; +} + +/* + * Uh, these should become the main single-value transfer routines ... + * They automatically use the right size if we just have the right + * pointer type ... + * + * As MIPS uses the same address space for kernel and user data, we + * can just do these as direct assignments. + * + * Careful to not + * (a) re-use the arguments for side effects (sizeof is ok) + * (b) require any knowledge of processes at this stage + */ +#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask) +#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask) + +/* + * The "__xxx" versions do not do address space checking, useful when + * doing multiple accesses to the same area (the user has to do the + * checks by hand with "access_ok()") + */ +#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) + +/* + * The "xxx_ret" versions return constant specified in third argument, if + * something bad happens. These macros can be optimized for the + * case of just returning from the function xxx_ret is used. + */ + +#define put_user_ret(x,ptr,ret) ({ \ +if (put_user(x,ptr)) return ret; }) + +#define get_user_ret(x,ptr,ret) ({ \ +if (get_user(x,ptr)) return ret; }) + +#define __put_user_ret(x,ptr,ret) ({ \ +if (__put_user(x,ptr)) return ret; }) + +#define __get_user_ret(x,ptr,ret) ({ \ +if (__get_user(x,ptr)) return ret; }) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct *)(x)) + +#define copy_to_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_to) +#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from) + +extern size_t __copy_user(void *__to, const void *__from, size_t __n); + +#define __copy_tofrom_user(to,from,n,v) ({ \ + void * __cu_to; \ + const void * __cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) \ + __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \ + __cu_len; \ +}) + +#define __get_user_nocheck(x,ptr,size) ({ \ +long __gu_err; \ +long __gu_val; \ +long __gu_addr; \ +__asm__("":"=r" (__gu_val)); \ +__gu_addr = (long) (ptr); \ +__gu_err = 0; \ +switch (size) { \ +case 1: __get_user_nocheck_asm("lb"); break; \ +case 2: __get_user_nocheck_asm("lh"); break; \ +case 4: __get_user_nocheck_asm("lw"); break; \ +case 8: __get_user_nocheck_asm("ld"); break; \ +default: __get_user_unknown(); break; \ +} x = (__typeof__(*(ptr))) __gu_val; __gu_err; }) + +#define __get_user_nocheck_asm(insn) \ +({ \ +__asm__ __volatile__( \ + "1:\t" insn "\t%1,%3\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\t.set\tnoat\n\t" \ + "la\t$1,2b\n\t" \ + "li\t%0,%4\n\t" \ + "jr\t$1\n\t" \ + ".set\tat\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b,3b\n\t" \ + ".previous" \ + :"=r" (__gu_err), "=r" (__gu_val) \ + :"0" (__gu_err), "o" (__m(__gu_addr)), "i" (-EFAULT) \ + :"$1"); }) + +#define __get_user_check(x,ptr,size,mask) ({ \ +long __gu_err; \ +long __gu_val; \ +long __gu_addr; \ +__asm__("":"=r" (__gu_val)); \ +__gu_addr = (long) (ptr); \ +__gu_err = -EFAULT; \ +if (__access_ok(__gu_addr,size,mask)) { \ +switch (size) { \ +case 1: __get_user_check_asm("lb"); break; \ +case 2: __get_user_check_asm("lh"); break; \ +case 4: __get_user_check_asm("lw"); break; \ +case 8: __get_user_check_asm("ld"); break; \ +default: __get_user_unknown(); break; \ +} } x = (__typeof__(*(ptr))) __gu_val; __gu_err; }) + +#define __get_user_check_asm(insn) \ +({ \ +__asm__ __volatile__( \ + "1:\t" insn "\t%1,%2\n\t" \ + "move\t%0,$0\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\t.set\tnoat\n\t" \ + "la\t$1,2b\n\t" \ + "jr\t$1\n\t" \ + ".set\tat\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b,3b\n\t" \ + ".previous" \ + :"=r" (__gu_err), "=r" (__gu_val) \ + :"o" (__m(__gu_addr)) \ + :"$1"); }) + +extern void __get_user_unknown(void); + +#define __put_user_nocheck(x,ptr,size) ({ \ +long __pu_err; \ +__typeof__(*(ptr)) __pu_val; \ +long __pu_addr; \ +__pu_val = (x); \ +__pu_addr = (long) (ptr); \ +__pu_err = 0; \ +switch (size) { \ +case 1: __put_user_nocheck_asm("sb"); break; \ +case 2: __put_user_nocheck_asm("sh"); break; \ +case 4: __put_user_nocheck_asm("sw"); break; \ +case 8: __put_user_nocheck_asm("sd"); break; \ +default: __put_user_unknown(); break; \ +} __pu_err; }) + +#define __put_user_nocheck_asm(insn) \ +({ \ +__asm__ __volatile__( \ + "1:\t" insn "\t%1,%2\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\t.set\tnoat\n\t" \ + "la\t$1,2b\n\t" \ + "li\t%0,%3\n\t" \ + "jr\t$1\n\t" \ + ".set\tat\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b,3b\n\t" \ + ".previous" \ + :"=r" (__pu_err) \ + :"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT) \ + :"$1"); }) + +#define __put_user_check(x,ptr,size,mask) ({ \ +long __pu_err; \ +__typeof__(*(ptr)) __pu_val; \ +long __pu_addr; \ +__pu_val = (x); \ +__pu_addr = (long) (ptr); \ +__pu_err = -EFAULT; \ +if (__access_ok(__pu_addr,size,mask)) { \ +switch (size) { \ +case 1: __put_user_check_asm("sb"); break; \ +case 2: __put_user_check_asm("sh"); break; \ +case 4: __put_user_check_asm("sw"); break; \ +case 8: __put_user_check_asm("sd"); break; \ +default: __put_user_unknown(); break; \ +} } __pu_err; }) + +#define __put_user_check_asm(insn) \ +({ \ +__asm__ __volatile__( \ + "1:\t" insn "\t%1,%2\n\t" \ + "move\t%0,$0\n" \ + "2:\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\t.set\tnoat\n\t" \ + "la\t$1,2b\n\t" \ + "jr\t$1\n\t" \ + ".set\tat\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b,3b\n\t" \ + ".previous" \ + :"=r" (__pu_err) \ + :"r" (__pu_val), "o" (__m(__pu_addr)) \ + :"$1"); }) + +extern void __put_user_unknown(void); + +#define copy_to_user_ret(to,from,n,retval) ({ \ +if (copy_to_user(to,from,n)) \ + return retval; \ +}) + +#define copy_from_user_ret(to,from,n,retval) ({ \ +if (copy_from_user(to,from,n)) \ + return retval; \ +}) + +#define __copy_to_user(to,from,n) \ + __copy_user((to),(from),(n)) + +#define __copy_from_user(to,from,n) \ + __copy_user((to),(from),(n)) + +#define __clear_user(addr,size) \ +({ \ + void *__cu_end; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + "1:\tsb\t$0,(%0)\n\t" \ + "bne\t%0,%1,1b\n\t" \ + "addiu\t%0,1\n" \ + "2:\t.set\treorder\n\t" \ + ".section\t.fixup,\"ax\"\n" \ + "3:\t.set\tnoat\n\t" \ + "la\t$1,2b\n\t" \ + "jr\t$1\n\t" \ + ".set\tat\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b,3b\n\t" \ + ".previous" \ + :"=r" (addr), "=r" (__cu_end) \ + :"0" (addr), "1" (addr + size - 1), "i" (-EFAULT) \ + :"$1","memory"); \ + size = __cu_end - (addr) - 1; \ +}) + +#define clear_user(addr,n) ({ \ +void * __cl_addr = (addr); \ +unsigned long __cl_size = (n); \ +if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \ +__clear_user(__cl_addr, __cl_size); \ +__cl_size; }) + +/* + * Returns: -EFAULT if exception before terminator, N if the entire + * buffer filled, else strlen. + */ +extern long __strncpy_from_user(char *__to, const char *__from, long __to_len); + +#define strncpy_from_user(dest,src,count) ({ \ + const void * __sc_src = (src); \ + long __sc_res = -EFAULT; \ + if (access_ok(VERIFY_READ, __sc_src, 0)) { \ + __sc_res = __strncpy_from_user(dest, __sc_src, count); \ +} __sc_res; }) + +/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ +extern long __strlen_user(const char *); + +extern inline long strlen_user(const char *str) +{ + return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0; +} + +struct exception_table_entry +{ + unsigned long insn; + unsigned long nextinsn; +}; + +/* Returns 0 if exception not found and fixup.unit otherwise. */ +extern unsigned long search_exception_table(unsigned long addr); + +/* Returns the new pc */ +#define fixup_exception(map_reg, fixup_unit, pc) \ +({ \ + fixup_unit; \ +}) + +#endif /* __ASM_MIPS_UACCESS_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/unaligned.h linux/include/asm-mips/unaligned.h --- v2.1.43/linux/include/asm-mips/unaligned.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/unaligned.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,101 @@ +/* + * Inline functions to do unaligned accesses. + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_UNALIGNED_H +#define __ASM_MIPS_UNALIGNED_H + +#include + +/* + * Load quad unaligned. + */ +extern __inline__ unsigned long ldq_u(unsigned long long * __addr) +{ + unsigned long long __res; + + __asm__("uld\t%0,(%1)" + :"=&r" (__res) + :"r" (__addr)); + + return __res; +} + +/* + * Load long unaligned. + */ +extern __inline__ unsigned long ldl_u(unsigned int * __addr) +{ + unsigned long __res; + + __asm__("ulw\t%0,(%1)" + :"=&r" (__res) + :"r" (__addr)); + + return __res; +} + +/* + * Load word unaligned. + */ +extern __inline__ unsigned long ldw_u(unsigned short * __addr) +{ + unsigned long __res; + + __asm__("ulh\t%0,(%1)" + :"=&r" (__res) + :"r" (__addr)); + + return __res; +} + +/* + * Store quad ununaligned. + */ +extern __inline__ void stq_u(unsigned long __val, unsigned long long * __addr) +{ + __asm__ __volatile__( + "usd\t%0,(%1)" + : /* No results */ + :"r" (__val), + "r" (__addr)); +} + +/* + * Store long ununaligned. + */ +extern __inline__ void stl_u(unsigned long __val, unsigned int * __addr) +{ + __asm__ __volatile__( + "usw\t%0,(%1)" + : /* No results */ + :"r" (__val), + "r" (__addr)); +} + +/* + * Store word ununaligned. + */ +extern __inline__ void stw_u(unsigned long __val, unsigned short * __addr) +{ + __asm__ __volatile__( + "ush\t%0,(%1)" + : /* No results */ + :"r" (__val), + "r" (__addr)); +} + +#define get_unaligned(ptr) \ + ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) + +#define put_unaligned(val, ptr) \ + ({ __typeof__(*(ptr)) __tmp = (val); \ + memcpy((ptr), &__tmp, sizeof(*(ptr))); \ + (void)0; }) + +#endif /* __ASM_MIPS_UNALIGNED_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h --- v2.1.43/linux/include/asm-mips/unistd.h Thu May 29 21:53:08 1997 +++ linux/include/asm-mips/unistd.h Thu Jun 26 12:33:40 1997 @@ -5,16 +5,18 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + * + * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto + * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A */ #ifndef __ASM_MIPS_UNISTD_H #define __ASM_MIPS_UNISTD_H /* * 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 ... + * compatibility with RISC/os and IRIX. We'll see how to deal with the + * various "real" BSD variants like Ultrix, NetBSD ... */ /* @@ -1067,7 +1069,7 @@ #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_reserved82 (__NR_Linux + 82) #define __NR_symlink (__NR_Linux + 83) #define __NR_oldlstat (__NR_Linux + 84) #define __NR_readlink (__NR_Linux + 85) @@ -1137,19 +1139,49 @@ #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_fdatasync (__NR_Linux + 152) +#define __NR__sysctl (__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) -#define __NR_nfsservctl (__NR_Linux + 158) - +#define __NR_sched_setparam (__NR_Linux + 158) +#define __NR_sched_getparam (__NR_Linux + 159) +#define __NR_sched_setscheduler (__NR_Linux + 160) +#define __NR_sched_getscheduler (__NR_Linux + 161) +#define __NR_sched_yield (__NR_Linux + 162) +#define __NR_sched_get_priority_max (__NR_Linux + 163) +#define __NR_sched_get_priority_min (__NR_Linux + 164) +#define __NR_sched_rr_get_interval (__NR_Linux + 165) +#define __NR_nanosleep (__NR_Linux + 166) +#define __NR_mremap (__NR_Linux + 167) +#define __NR_accept (__NR_Linux + 168) +#define __NR_bind (__NR_Linux + 169) +#define __NR_connect (__NR_Linux + 170) +#define __NR_getpeername (__NR_Linux + 171) +#define __NR_getsockname (__NR_Linux + 172) +#define __NR_getsockopt (__NR_Linux + 173) +#define __NR_listen (__NR_Linux + 174) +#define __NR_recv (__NR_Linux + 175) +#define __NR_recvfrom (__NR_Linux + 176) +#define __NR_recvmsg (__NR_Linux + 177) +#define __NR_send (__NR_Linux + 178) +#define __NR_sendmsg (__NR_Linux + 179) +#define __NR_sendto (__NR_Linux + 180) +#define __NR_setsockopt (__NR_Linux + 181) +#define __NR_shutdown (__NR_Linux + 182) +#define __NR_socket (__NR_Linux + 183) +#define __NR_socketpair (__NR_Linux + 184) +#define __NR_setresuid (__NR_Linux + 185) +#define __NR_getresuid (__NR_Linux + 186) +#define __NR_query_module (__NR_Linux + 187) +#define __NR_poll (__NR_Linux + 188) +#define __NR_nfsservctl (__NR_Linux + 189) /* * Offset of the last Linux flavoured syscall */ -#define __NR_Linux_syscalls 158 +#define __NR_Linux_syscalls 189 #ifndef __LANGUAGE_ASSEMBLY__ @@ -1261,17 +1293,85 @@ __asm__ volatile ("move\t$4,%3\n\t" \ "move\t$5,%4\n\t" \ "move\t$6,%5\n\t" \ + "lw\t$2,%7\n\t" \ "move\t$7,%6\n\t" \ - "move\t$3,%7\n\t" \ + "subu\t$29,24\n\t" \ + "sw\t$2,16($29)\n\t" \ "li\t$2,%2\n\t" \ - "syscall" \ + "syscall\n\t" \ + "addiu\t$29,24" \ + : "=r" (__res), "=r" (__err) \ + : "i" (__NR_##name),"r" ((long)(a)), \ + "r" ((long)(b)), \ + "r" ((long)(c)), \ + "r" ((long)(d)), \ + "m" ((long)(e)) \ + : "$2","$4","$5","$6","$7"); \ +if (__err == 0) \ + return (type) __res; \ +errno = __res; \ +return -1; \ +} + +#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \ +type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \ +{ \ +register long __res __asm__ ("$2"); \ +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" \ + "lw\t$2,%7\n\t" \ + "lw\t$3,%8\n\t" \ + "move\t$7,%6\n\t" \ + "subu\t$29,24\n\t" \ + "sw\t$2,16($29)\n\t" \ + "sw\t$3,20($29)\n\t" \ + "li\t$2,%2\n\t" \ + "syscall\n\t" \ + "addiu\t$29,24" \ + : "=r" (__res), "=r" (__err) \ + : "i" (__NR_##name),"r" ((long)(a)), \ + "r" ((long)(b)), \ + "r" ((long)(c)), \ + "r" ((long)(d)), \ + "m" ((long)(e)), \ + "m" ((long)(f)) \ + : "$2","$3","$4","$5","$6","$7"); \ +if (__err == 0) \ + return (type) __res; \ +errno = __res; \ +return -1; \ +} + +#define _syscall7(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f,gtype,g) \ +type name (atype a,btype b,ctype c,dtype d,etype e,ftype f,gtype g) \ +{ \ +register long __res __asm__ ("$2"); \ +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" \ + "lw\t$2,%7\n\t" \ + "lw\t$3,%8\n\t" \ + "move\t$7,%6\n\t" \ + "subu\t$29,32\n\t" \ + "sw\t$2,16($29)\n\t" \ + "lw\t$2,%9\n\t" \ + "sw\t$3,20($29)\n\t" \ + "sw\t$2,24($29)\n\t" \ + "li\t$2,%2\n\t" \ + "syscall\n\t" \ + "addiu\t$29,32" \ : "=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"); \ + "m" ((long)(e)), \ + "m" ((long)(f)), \ + "m" ((long)(g)) \ + : "$2","$3","$4","$5","$6","$7"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1332,13 +1432,13 @@ "li\t$2,%1\n\t" "syscall\n\t" "beq\t$8,$sp,1f\n\t" - "subu\t$sp,16\n\t" /* delay slot */ + "subu\t$sp,32\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" + "1:\taddiu\t$sp,32\n\t" "move\t%0,$2\n\t" ".set\treorder" :"=r" (retval) diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/user.h linux/include/asm-mips/user.h --- v2.1.43/linux/include/asm-mips/user.h Wed Dec 13 02:39:47 1995 +++ linux/include/asm-mips/user.h Thu Jun 26 12:33:40 1997 @@ -9,8 +9,8 @@ /* * 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: + * linux we use the `trad-core' bfd, NOT the irix-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 @@ -30,7 +30,7 @@ * to write an integer number of pages. */ struct user { - unsigned long regs[EF_SIZE/8+32]; /* integer and fp regs */ + unsigned long regs[EF_SIZE/4+64]; /* 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) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/vector.h linux/include/asm-mips/vector.h --- v2.1.43/linux/include/asm-mips/vector.h Thu Apr 11 23:49:44 1996 +++ linux/include/asm-mips/vector.h Thu Jun 26 12:33:40 1997 @@ -5,19 +5,24 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle */ #ifndef __ASM_MIPS_VECTOR_H #define __ASM_MIPS_VECTOR_H /* + * These vector structures are not very good to maintain - they'd probably + * grow to at leat three times the size - so I'll remove 'em and replace + * the with lots of ordinary variables. + */ +extern void (*irq_setup)(void); +extern asmlinkage void (*fd_cacheflush)(const void *addr, size_t size); + +/* * 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. */ @@ -37,25 +42,13 @@ 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 + * How to access the RTC register of the 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 dependent features. - * - * FIXME: This vector isn't being used yet - */ -struct cpu { - int dummy; /* keep GCC from complaining */ + unsigned char (*rtc_read_data)(unsigned long addr); + void (*rtc_write_data)(unsigned char data, unsigned long addr); }; extern struct feature *feature; -extern struct cpu *cpu; #endif /* __ASM_MIPS_VECTOR_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-mips/watch.h linux/include/asm-mips/watch.h --- v2.1.43/linux/include/asm-mips/watch.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/watch.h Thu Jun 26 12:33:40 1997 @@ -0,0 +1,38 @@ +/* + * Functions to use the watch register debugging functionality. + * + * 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) 1996 by Ralf Baechle + */ +#ifndef __ASM_WATCH_H +#define __ASM_WATCH_H + +#include + +/* + * Types of reference for watch_set() + */ +enum wref_type { + wr_save = 1, + wr_load = 2 +}; + +extern asmlinkage unsigned int watch_available; +extern asmlinkage __watch_set(unsigned long addr, enum wref_type ref); +extern asmlinkage __watch_clear(void); +extern asmlinkage __watch_reenable(void); + +#define watch_set(addr, ref) \ + if (watch_available) \ + __watch_set(addr, ref) +#define watch_clear() \ + if (watch_available) \ + __watch_clear() +#define watch_reenable() \ + if (watch_available) \ + __watch_reenable() + +#endif __ASM_WATCH_H diff -u --recursive --new-file v2.1.43/linux/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h --- v2.1.43/linux/include/asm-ppc/ioctls.h Mon May 27 02:00:59 1996 +++ linux/include/asm-ppc/ioctls.h Thu Jun 26 12:33:40 1997 @@ -83,6 +83,8 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h --- v2.1.43/linux/include/asm-sparc/pgtable.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/pgtable.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.60 1997/04/14 17:05:16 jj Exp $ */ +/* $Id: pgtable.h,v 1.61 1997/06/06 10:56:34 jj Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -368,7 +368,7 @@ #define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry) #define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry) -extern __inline__ unsigned int +extern __inline__ unsigned long __get_phys (unsigned long addr) { switch (sparc_cpu_model){ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h --- v2.1.43/linux/include/asm-sparc64/asm_offsets.h Thu May 29 21:53:09 1997 +++ linux/include/asm-sparc64/asm_offsets.h Thu Jun 26 12:33:40 1997 @@ -104,14 +104,8 @@ #define ASIZ_task_it_virt_incr 0x00000008 #define AOFF_task_real_timer 0x000001f8 #define ASIZ_task_real_timer 0x00000028 -#define AOFF_task_utime 0x00000220 -#define ASIZ_task_utime 0x00000008 -#define AOFF_task_stime 0x00000228 -#define ASIZ_task_stime 0x00000008 -#define AOFF_task_cutime 0x00000230 -#define ASIZ_task_cutime 0x00000008 -#define AOFF_task_cstime 0x00000238 -#define ASIZ_task_cstime 0x00000008 +#define AOFF_task_times 0x00000220 +#define ASIZ_task_times 0x00000020 #define AOFF_task_start_time 0x00000240 #define ASIZ_task_start_time 0x00000008 #define AOFF_task_min_flt 0x00000248 @@ -245,12 +239,12 @@ #define AOFF_thread_sstk_info 0x00000590 #define ASIZ_thread_sstk_info 0x00000010 #define AOFF_thread_current_ds 0x000005a0 -#define ASIZ_thread_current_ds 0x00000004 -#define AOFF_thread_new_signal 0x000005a4 -#define ASIZ_thread_new_signal 0x00000004 -#define AOFF_thread_kregs 0x000005a8 +#define ASIZ_thread_current_ds 0x00000008 +#define AOFF_thread_new_signal 0x000005a8 +#define ASIZ_thread_new_signal 0x00000008 +#define AOFF_thread_kregs 0x000005b0 #define ASIZ_thread_kregs 0x00000008 -#define AOFF_thread_core_exec 0x000005b0 +#define AOFF_thread_core_exec 0x000005b8 #define ASIZ_thread_core_exec 0x00000020 #endif /* __ASM_OFFSETS_H__ */ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- v2.1.43/linux/include/asm-sparc64/bitops.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/bitops.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.16 1997/05/28 13:48:56 jj Exp $ +/* $Id: bitops.h,v 1.17 1997/06/14 17:35:05 davem Exp $ * bitops.h: Bit string operations on the V9. * * Copyright 1996 David S. Miller (davem@caip.rutgers.edu) @@ -260,22 +260,12 @@ #define find_first_zero_le_bit(addr, size) \ find_next_zero_le_bit((addr), (size), 0) -extern __inline__ unsigned long __swab64(unsigned long value) -{ - return (((value>>56) & 0x00000000000000ff) | - ((value>>40) & 0x000000000000ff00) | - ((value>>24) & 0x0000000000ff0000) | - ((value>>8) & 0x00000000ff000000) | - ((value<<8) & 0x000000ff00000000) | - ((value<<24) & 0x0000ff0000000000) | - ((value<<40) & 0x00ff000000000000) | - ((value<<56) & 0xff00000000000000)); -} - extern __inline__ unsigned long __swab64p(unsigned long *addr) { unsigned long ret; - __asm__ __volatile__ ("ldxa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL)); + __asm__ __volatile__ ("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); return ret; } diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/byteorder.h linux/include/asm-sparc64/byteorder.h --- v2.1.43/linux/include/asm-sparc64/byteorder.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/byteorder.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: byteorder.h,v 1.5 1997/05/28 11:35:41 jj Exp $ */ +/* $Id: byteorder.h,v 1.6 1997/06/14 17:35:07 davem Exp $ */ #ifndef _SPARC64_BYTEORDER_H #define _SPARC64_BYTEORDER_H @@ -56,21 +56,27 @@ extern __inline__ __u16 cpu_to_le16p(__u16 *addr) { __u16 ret; - __asm__ __volatile__ ("lduha [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL)); + __asm__ __volatile__ ("lduha [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); return ret; } extern __inline__ __u32 cpu_to_le32p(__u32 *addr) { __u32 ret; - __asm__ __volatile__ ("lduwa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL)); + __asm__ __volatile__ ("lduwa [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); return ret; } extern __inline__ __u64 cpu_to_le64p(__u64 *addr) { __u64 ret; - __asm__ __volatile__ ("ldxa [%1] %2, %0" : "=r" (ret) : "r" (addr), "i" (ASI_PL)); + __asm__ __volatile__ ("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); return ret; } extern __inline__ __u16 cpu_to_be16p(__u16 *addr) { return *addr; } diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h --- v2.1.43/linux/include/asm-sparc64/elf.h Sat May 24 09:10:25 1997 +++ linux/include/asm-sparc64/elf.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: elf.h,v 1.6 1997/05/17 11:51:27 davem Exp $ */ +/* $Id: elf.h,v 1.7 1997/06/14 21:28:07 davem Exp $ */ #ifndef __ASM_SPARC64_ELF_H #define __ASM_SPARC64_ELF_H @@ -32,7 +32,9 @@ /* * This is used to ensure we don't load something for the wrong architecture. */ +#ifndef elf_check_arch #define elf_check_arch(x) ((x) == ELF_ARCH) /* Might be EM_SPARC64 or EM_SPARC */ +#endif #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 8192 diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/fbio.h linux/include/asm-sparc64/fbio.h --- v2.1.43/linux/include/asm-sparc64/fbio.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc64/fbio.h Thu Jun 26 12:33:40 1997 @@ -48,10 +48,6 @@ }; #define FBIOGTYPE _IOR('F', 0, struct fbtype) -/* Used by FBIOPUTCMAP - * - * XXX 32-bit binary compatability item... -DaveM - */ struct fbcmap { int index; /* first element (0 origin) */ int count; @@ -104,7 +100,6 @@ #define FB_CUR_SETSHAPE 0x10 /* set shape */ #define FB_CUR_SETALL 0x1F /* all of the above */ -/* XXX 32-bit binary compatability item... -DaveM */ struct fbcursor { short set; /* what to set, choose from the list above */ short enable; /* cursor on/off */ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/fs_mount.h linux/include/asm-sparc64/fs_mount.h --- v2.1.43/linux/include/asm-sparc64/fs_mount.h Tue May 13 22:41:18 1997 +++ linux/include/asm-sparc64/fs_mount.h Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* $Id: fs_mount.h,v 1.2 1997/04/18 14:34:46 jj Exp $ - * fs_mount.h: Definitions for mount structure conversions. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#ifndef __ASM_FS_MOUNT_H -#define __ASM_FS_MOUNT_H - -#if defined(CONFIG_SPARC32_COMPAT) || defined(CONFIG_SPARC32_COMPAT_MODULE) - -#include - -/* We need this to convert 32bit mount structures to 64bit */ - -extern void *do_ncp_super_data_conv(void *raw_data); -extern void *do_smb_super_data_conv(void *raw_data); - -extern __inline__ void *ncp_super_data_conv(void *raw_data) -{ - if (current->tss.flags & SPARC_FLAG_32BIT) - return do_ncp_super_data_conv(raw_data); - else - return raw_data; -} - -extern __inline__ void *smb_super_data_conv(void *raw_data) -{ - if (current->tss.flags & SPARC_FLAG_32BIT) - return do_smb_super_data_conv(raw_data); - else - return raw_data; -} - -#else /* CONFIG_SPARC32_COMPAT* */ - -#define ncp_super_data_conv(__x) __x -#define smb_super_data_conv(__x) __x - -#endif /* CONFIG_SPARC32_COMPAT* */ - -#define nfs_super_data_conv(__x) __x - -#endif /* __ASM_FS_MOUNT_H */ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/head.h linux/include/asm-sparc64/head.h --- v2.1.43/linux/include/asm-sparc64/head.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/head.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: head.h,v 1.22 1997/06/02 06:33:40 davem Exp $ */ +/* $Id: head.h,v 1.23 1997/06/14 13:25:50 davem Exp $ */ #ifndef _SPARC64_HEAD_H #define _SPARC64_HEAD_H @@ -207,16 +207,23 @@ #define SPILL_2_GENERIC(xxx) \ wr %g0, xxx, %asi; \ srl %sp, 0, %sp; \ - stda %l0, [%sp + 0x00] %asi; \ - stda %l2, [%sp + 0x08] %asi; \ - stda %l4, [%sp + 0x10] %asi; \ - stda %l6, [%sp + 0x18] %asi; \ - stda %i0, [%sp + 0x20] %asi; \ - stda %i2, [%sp + 0x28] %asi; \ - stda %i4, [%sp + 0x30] %asi; \ - stda %i6, [%sp + 0x38] %asi; \ + stwa %l0, [%sp + 0x00] %asi; \ + stwa %l1, [%sp + 0x04] %asi; \ + stwa %l2, [%sp + 0x08] %asi; \ + stwa %l3, [%sp + 0x0c] %asi; \ + stwa %l4, [%sp + 0x10] %asi; \ + stwa %l5, [%sp + 0x14] %asi; \ + stwa %l6, [%sp + 0x18] %asi; \ + stwa %l7, [%sp + 0x1c] %asi; \ + stwa %i0, [%sp + 0x20] %asi; \ + stwa %i1, [%sp + 0x24] %asi; \ + stwa %i2, [%sp + 0x28] %asi; \ + stwa %i3, [%sp + 0x2c] %asi; \ + stwa %i4, [%sp + 0x30] %asi; \ + stwa %i5, [%sp + 0x34] %asi; \ + stwa %i6, [%sp + 0x38] %asi; \ + stwa %i7, [%sp + 0x3c] %asi; \ saved; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; \ nop; nop; nop; nop; nop; nop; \ b,a,pt %xcc, spill_fixup_mna; \ b,a,pt %xcc, spill_fixup; @@ -287,16 +294,23 @@ #define FILL_2_GENERIC(xxx) \ wr %g0, xxx, %asi; \ srl %sp, 0, %sp; \ - ldda [%sp + 0x00] %asi, %l0; \ - ldda [%sp + 0x08] %asi, %l2; \ - ldda [%sp + 0x10] %asi, %l4; \ - ldda [%sp + 0x18] %asi, %l6; \ - ldda [%sp + 0x20] %asi, %i0; \ - ldda [%sp + 0x28] %asi, %i2; \ - ldda [%sp + 0x30] %asi, %i4; \ - ldda [%sp + 0x38] %asi, %i6; \ + lduwa [%sp + 0x00] %asi, %l0; \ + lduwa [%sp + 0x04] %asi, %l1; \ + lduwa [%sp + 0x08] %asi, %l2; \ + lduwa [%sp + 0x0c] %asi, %l3; \ + lduwa [%sp + 0x10] %asi, %l4; \ + lduwa [%sp + 0x14] %asi, %l5; \ + lduwa [%sp + 0x18] %asi, %l6; \ + lduwa [%sp + 0x1c] %asi, %l7; \ + lduwa [%sp + 0x20] %asi, %i0; \ + lduwa [%sp + 0x24] %asi, %i1; \ + lduwa [%sp + 0x28] %asi, %i2; \ + lduwa [%sp + 0x2c] %asi, %i3; \ + lduwa [%sp + 0x30] %asi, %i4; \ + lduwa [%sp + 0x34] %asi, %i5; \ + lduwa [%sp + 0x38] %asi, %i6; \ + lduwa [%sp + 0x3c] %asi, %i7; \ restored; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; \ nop; nop; nop; nop; nop; nop; \ b,a,pt %xcc, fill_fixup_mna; \ b,a,pt %xcc, fill_fixup; diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/ioctls.h linux/include/asm-sparc64/ioctls.h --- v2.1.43/linux/include/asm-sparc64/ioctls.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/ioctls.h Thu Jun 26 12:33:40 1997 @@ -1,14 +1,9 @@ -/* $Id: ioctls.h,v 1.2 1997/04/04 00:50:18 davem Exp $ */ +/* $Id: ioctls.h,v 1.3 1997/06/14 17:35:08 davem Exp $ */ #ifndef _ASM_SPARC64_IOCTLS_H #define _ASM_SPARC64_IOCTLS_H #include -/* XXX 32-bit binary compatability issues, I am sure that - * XXX only IOCTL's which reference structures will be of - * XXX concern and these are easily fabricated using wrappers. - */ - /* Big T */ #define TCGETA _IOR('T', 1, struct termio) #define TCSETA _IOW('T', 2, struct termio) @@ -24,7 +19,7 @@ /* Note that all the ioctls that are not available in Linux have a * double underscore on the front to: a) avoid some programs to - * thing we support some ioctls under Linux (autoconfiguration stuff) + * think we support some ioctls under Linux (autoconfiguration stuff) */ /* Little t */ #define TIOCGETD _IOR('t', 0, int) diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- v2.1.43/linux/include/asm-sparc64/mmu_context.h Thu May 29 21:53:09 1997 +++ linux/include/asm-sparc64/mmu_context.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: mmu_context.h,v 1.10 1997/05/23 09:35:55 jj Exp $ */ +/* $Id: mmu_context.h,v 1.11 1997/06/13 14:03:04 davem Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H @@ -42,11 +42,11 @@ spitfire_put_itlb_data(entry, 0x0UL); } membar("#Sync"); - flushi(PAGE_OFFSET); + __asm__ __volatile__("flush %g4"); restore_flags(flags); ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION; - if(!ctx) + if(ctx == 1) /* _not_ zero! */ ctx = CTX_FIRST_VERSION; } tlb_context_cache = ctx + 1; @@ -55,30 +55,32 @@ extern __inline__ void get_mmu_context(struct task_struct *tsk) { + register unsigned long paddr asm("o5"); struct mm_struct *mm = tsk->mm; - if(mm && - !(tsk->tss.flags & SPARC_FLAG_KTHREAD) && + flushw_user(); + if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD) && !(tsk->flags & PF_EXITING)) { unsigned long ctx = tlb_context_cache; - register unsigned long paddr asm("o5"); - - flushw_user(); if((mm->context ^ ctx) & CTX_VERSION_MASK) get_new_mmu_context(mm, ctx); - tsk->tss.ctx = (mm->context & 0x1fff); - spitfire_set_secondary_context(tsk->tss.current_ds ? - mm->context : 0); - paddr = __pa(mm->pgd); - __asm__ __volatile__(" - rdpr %%pstate, %%o4 - wrpr %%o4, %1, %%pstate - mov %0, %%g7 - wrpr %%o4, 0x0, %%pstate - " : /* no outputs */ - : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE) - : "o4"); - } + + /* Don't worry, set_fs() will restore it... */ + tsk->tss.ctx = (tsk->tss.current_ds ? + (mm->context & 0x1fff) : 0); + } else + tsk->tss.ctx = 0; + spitfire_set_secondary_context(tsk->tss.ctx); + __asm__ __volatile__("flush %g4"); + paddr = __pa(mm->pgd); + __asm__ __volatile__(" + rdpr %%pstate, %%o4 + wrpr %%o4, %1, %%pstate + mov %0, %%g7 + wrpr %%o4, 0x0, %%pstate + " : /* no outputs */ + : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE) + : "o4"); } #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h --- v2.1.43/linux/include/asm-sparc64/page.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/page.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.8 1997/03/26 12:24:21 davem Exp $ */ +/* $Id: page.h,v 1.9 1997/06/14 21:28:09 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -18,7 +18,14 @@ #ifndef __ASSEMBLY__ -#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) +#define clear_page(page) \ + __asm__ __volatile__( "mov %%o7, %%g3\n\t" \ + "call __bzero_1page\n\t" \ + " mov %0, %%g2\n\t" \ + : /* No outputs */ \ + : "r" (page) \ + : "g1", "g2", "g3") + #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) #define STRICT_MM_TYPECHECKS diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h --- v2.1.43/linux/include/asm-sparc64/pgtable.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/pgtable.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.34 1997/06/02 06:33:41 davem Exp $ +/* $Id: pgtable.h,v 1.37 1997/06/13 14:03:06 davem Exp $ * pgtable.h: SpitFire page table operations. * * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -83,13 +83,12 @@ #define _PAGE_ACCESSED 0x0000000000000400 /* Accessed Page (ie. referenced) */ #define _PAGE_READ 0x0000000000000200 /* Readable SW Bit */ #define _PAGE_WRITE 0x0000000000000100 /* Writable SW Bit */ -#define _PAGE_PRIV 0x0000000000000080 /* Software privilege bit */ #define _PAGE_CACHE (_PAGE_CP | _PAGE_CV) #define __DIRTY_BITS (_PAGE_MODIFIED | _PAGE_WRITE | _PAGE_W) #define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_READ | _PAGE_R) -#define __PRIV_BITS (_PAGE_P | _PAGE_PRIV) +#define __PRIV_BITS _PAGE_P #define PAGE_NONE __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ __PRIV_BITS | __ACCESS_BITS) @@ -112,7 +111,7 @@ #define _PAGE_CHG_MASK (_PFN_MASK | _PAGE_MODIFIED | _PAGE_ACCESSED | _PAGE_PRESENT) -#define pg_iobits (_PAGE_VALID | __PRIV_BITS | __ACCESS_BITS | _PAGE_E) +#define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E) #define __P000 PAGE_NONE #define __P001 PAGE_READONLY @@ -244,7 +243,7 @@ 1: stxa %%g0, [%%g3] %3 stxa %%g0, [%%g3] %4 - be,a,pt %%icc, 1f + be,pt %%icc, 1f nop stxa %%g2, [%%g7] %2 1: @@ -268,7 +267,7 @@ start &= PAGE_MASK; save_and_cli(flags); if(new_ctx != old_ctx) - spitfire_set_secondary_context(mm->context); + spitfire_set_secondary_context(new_ctx); while(start < end) { spitfire_flush_dtlb_secondary_page(start); spitfire_flush_itlb_secondary_page(start); @@ -299,7 +298,7 @@ 1: stxa %%g0, [%%g3] %3 stxa %%g0, [%%g3] %4 - be,a,pt %%icc, 1f + be,pt %%icc, 1f nop stxa %%g2, [%%g7] %2 1: @@ -638,7 +637,7 @@ { pte_t pte; pte_val(pte) = (type<>PAGE_SHIFT) & 0xff)) #define SWP_OFFSET(entry) ((entry) >> (PAGE_SHIFT+8)) @@ -651,16 +650,16 @@ pmd_t *pmdp; pte_t *ptep; - pgdp = pgd_offset (current->mm, addr); + pgdp = pgd_offset_k (addr); pmdp = pmd_offset (pgdp, addr); ptep = pte_offset (pmdp, addr); return pte_val (*ptep) & _PAGE_PADDR; } -extern __inline__ unsigned int +extern __inline__ unsigned long __get_phys (unsigned long addr) { - return (sun4u_get_pte (addr) & 0x0fffffff); + return sun4u_get_pte (addr); } extern __inline__ int diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h --- v2.1.43/linux/include/asm-sparc64/processor.h Thu May 29 21:53:09 1997 +++ linux/include/asm-sparc64/processor.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.27 1997/05/23 09:35:52 jj Exp $ +/* $Id: processor.h,v 1.29 1997/06/16 04:45:05 davem Exp $ * include/asm-sparc64/processor.h * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -56,7 +56,8 @@ unsigned long sig_desc; struct sigstack sstk_info; - int current_ds, new_signal; + unsigned long current_ds; + unsigned long new_signal; struct pt_regs *kregs; @@ -135,7 +136,7 @@ "stx %%g0, [%0 + %2 + 0x78]\n\t" \ "wrpr %%g0, (1 << 3), %%wstate\n\t" \ : \ - : "r" (regs), "r" (sp - REGWIN_SZ), \ + : "r" (regs), "r" (sp - REGWIN_SZ - STACK_BIAS), \ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ } while(0) diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/resource.h linux/include/asm-sparc64/resource.h --- v2.1.43/linux/include/asm-sparc64/resource.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/resource.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: resource.h,v 1.2 1997/04/04 00:50:27 davem Exp $ +/* $Id: resource.h,v 1.3 1997/06/14 17:35:09 davem Exp $ * resource.h: Resource definitions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -25,7 +25,6 @@ #define RLIM_NLIMITS 10 #ifdef __KERNEL__ -/* XXX 32-bit binary compatability... */ #define INIT_RLIMITS \ { \ {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \ diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/sigcontext.h linux/include/asm-sparc64/sigcontext.h --- v2.1.43/linux/include/asm-sparc64/sigcontext.h Mon Apr 14 16:28:24 1997 +++ linux/include/asm-sparc64/sigcontext.h Thu Jun 26 12:33:40 1997 @@ -1,14 +1,9 @@ -/* $Id: sigcontext.h,v 1.4 1997/04/04 00:50:28 davem Exp $ */ +/* $Id: sigcontext.h,v 1.6 1997/06/16 00:29:25 richard Exp $ */ #ifndef __SPARC64_SIGCONTEXT_H #define __SPARC64_SIGCONTEXT_H #include -/* XXX This gets exported to userland as well as kernel, it is probably - * XXX riddled with many hard to find 32-bit binary compatability issues. - * XXX Signals and this file need to be investigated heavily. -DaveM - */ - #define SUNOS_MAXWIN 31 #ifndef __ASSEMBLY__ @@ -47,12 +42,12 @@ struct sigcontext { int sigc_onstack; /* state to restore */ int sigc_mask; /* sigmask to restore */ - int sigc_sp; /* stack pointer */ - int sigc_pc; /* program counter */ - int sigc_npc; /* next program counter */ - int sigc_psr; /* for condition codes etc */ - int sigc_g1; /* User uses these two registers */ - int sigc_o0; /* within the trampoline code. */ + unsigned long sigc_sp; /* stack pointer */ + unsigned long sigc_pc; /* program counter */ + unsigned long sigc_npc; /* next program counter */ + unsigned long sigc_psr; /* for condition codes etc */ + unsigned long sigc_g1; /* User uses these two registers */ + unsigned long sigc_o0; /* within the trampoline code. */ /* Now comes information regarding the users window set * at the time of the signal. diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h --- v2.1.43/linux/include/asm-sparc64/system.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/system.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.22 1997/06/01 10:27:28 davem Exp $ */ +/* $Id: system.h,v 1.23 1997/06/16 06:17:06 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -200,15 +200,15 @@ { unsigned long temp; __asm__ __volatile__(" - ldx [%3], %1 -1: + mov %0, %%g1 +1: ldx [%3], %1 casx [%3], %1, %0 cmp %1, %0 bne,a,pn %%xcc, 1b - ldx [%3], %1 + mov %%g1, %0 " : "=&r" (val), "=&r" (temp) : "0" (val), "r" (m) - : "cc"); + : "g1", "cc"); return val; } diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h --- v2.1.43/linux/include/asm-sparc64/uaccess.h Mon Jun 16 16:36:00 1997 +++ linux/include/asm-sparc64/uaccess.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.13 1997/05/29 12:45:04 jj Exp $ */ +/* $Id: uaccess.h,v 1.14 1997/06/13 14:03:11 davem Exp $ */ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H @@ -22,26 +22,26 @@ * * "For historical reasons, these macros are grossly misnamed." -Linus */ -#define KERNEL_DS 0 -#define USER_DS -1 +#define KERNEL_DS 0x00 +#define USER_DS 0x2B /* har har har */ #define VERIFY_READ 0 #define VERIFY_WRITE 1 #define get_fs() (current->tss.current_ds) #define get_ds() (KERNEL_DS) -extern __inline__ void set_fs(int val) -{ - if (val != current->tss.current_ds) { - if (val == KERNEL_DS) { - flushw_user (); - spitfire_set_secondary_context (0); - } else { - spitfire_set_secondary_context (current->mm->context); - } - current->tss.current_ds = val; - } -} +#define set_fs(val) \ +do { \ + current->tss.current_ds = (val); \ + if ((val) == KERNEL_DS) { \ + flushw_user (); \ + current->tss.ctx = 0; \ + } else { \ + current->tss.ctx = (current->mm->context & 0x1fff); \ + } \ + spitfire_set_secondary_context(current->tss.ctx); \ + __asm__ __volatile__("flush %g4"); \ +} while(0) #define __user_ok(addr,size) 1 #define __kernel_ok (get_fs() == KERNEL_DS) diff -u --recursive --new-file v2.1.43/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h --- v2.1.43/linux/include/asm-sparc64/unistd.h Thu May 29 21:53:10 1997 +++ linux/include/asm-sparc64/unistd.h Thu Jun 26 12:33:40 1997 @@ -1,4 +1,4 @@ -/* $Id: unistd.h,v 1.5 1997/05/21 10:21:57 jj Exp $ */ +/* $Id: unistd.h,v 1.7 1997/06/16 05:37:44 davem Exp $ */ #ifndef _SPARC64_UNISTD_H #define _SPARC64_UNISTD_H @@ -113,35 +113,35 @@ #define __NR_setdopt 94 /* SunOS Specific */ #define __NR_fsync 95 /* Common */ #define __NR_setpriority 96 /* Common */ -#define __NR_socket 97 /* SunOS Specific */ -#define __NR_connect 98 /* SunOS Specific */ -#define __NR_accept 99 /* SunOS Specific */ +#define __NR_socket 97 /* Common */ +#define __NR_connect 98 /* Common */ +#define __NR_accept 99 /* Common */ #define __NR_getpriority 100 /* Common */ -#define __NR_send 101 /* SunOS Specific */ -#define __NR_recv 102 /* SunOS Specific */ +#define __NR_send 101 /* Common */ +#define __NR_recv 102 /* Common */ /* #define __NR_ni_syscall 103 ENOSYS under SunOS */ -#define __NR_bind 104 /* SunOS Specific */ -#define __NR_setsockopt 105 /* SunOS Specific */ -#define __NR_listen 106 /* SunOS Specific */ +#define __NR_bind 104 /* Common */ +#define __NR_setsockopt 105 /* Common */ +#define __NR_listen 106 /* Common */ /* #define __NR_ni_syscall 107 ENOSYS under SunOS */ #define __NR_sigvec 108 /* SunOS Specific */ #define __NR_sigblock 109 /* SunOS Specific */ #define __NR_sigsetmask 110 /* SunOS Specific */ #define __NR_sigpause 111 /* SunOS Specific */ #define __NR_sigstack 112 /* SunOS Specific */ -#define __NR_recvmsg 113 /* SunOS Specific */ -#define __NR_sendmsg 114 /* SunOS Specific */ +#define __NR_recvmsg 113 /* Common */ +#define __NR_sendmsg 114 /* Common */ #define __NR_vtrace 115 /* SunOS Specific */ #define __NR_gettimeofday 116 /* Common */ #define __NR_getrusage 117 /* Common */ -#define __NR_getsockopt 118 /* SunOS Specific */ +#define __NR_getsockopt 118 /* Common */ /* #define __NR_ni_syscall 119 ENOSYS under SunOS */ #define __NR_readv 120 /* Common */ #define __NR_writev 121 /* Common */ #define __NR_settimeofday 122 /* Common */ #define __NR_fchown 123 /* Common */ #define __NR_fchmod 124 /* Common */ -#define __NR_recvfrom 125 /* SunOS Specific */ +#define __NR_recvfrom 125 /* Common */ #define __NR_setreuid 126 /* Common */ #define __NR_setregid 127 /* Common */ #define __NR_rename 128 /* Common */ @@ -149,15 +149,15 @@ #define __NR_ftruncate 130 /* Common */ #define __NR_flock 131 /* Common */ /* #define __NR_ni_syscall 132 ENOSYS under SunOS */ -#define __NR_sendto 133 /* SunOS Specific */ -#define __NR_shutdown 134 /* SunOS Specific */ -#define __NR_socketpair 135 /* SunOS Specific */ +#define __NR_sendto 133 /* Common */ +#define __NR_shutdown 134 /* Common */ +#define __NR_socketpair 135 /* Common */ #define __NR_mkdir 136 /* Common */ #define __NR_rmdir 137 /* Common */ #define __NR_utimes 138 /* SunOS Specific */ /* #define __NR_ni_syscall 139 ENOSYS under SunOS */ #define __NR_adjtime 140 /* SunOS Specific */ -#define __NR_getpeername 141 /* SunOS Specific */ +#define __NR_getpeername 141 /* Common */ #define __NR_gethostid 142 /* SunOS Specific */ /* #define __NR_ni_syscall 143 ENOSYS under SunOS */ #define __NR_getrlimit 144 /* Common */ @@ -166,7 +166,7 @@ /* #define __NR_ni_syscall 147 ENOSYS under SunOS */ /* #define __NR_ni_syscall 148 ENOSYS under SunOS */ /* #define __NR_ni_syscall 149 ENOSYS under SunOS */ -#define __NR_getsockname 150 /* SunOS Specific */ +#define __NR_getsockname 150 /* Common */ #define __NR_getmsg 151 /* SunOS Specific */ #define __NR_putmsg 152 /* SunOS Specific */ #define __NR_poll 153 /* SunOS Specific */ @@ -467,6 +467,7 @@ #endif /* __KERNEL_SYSCALLS__ */ +#ifdef __KERNEL__ /* sysconf options, for SunOS compatibility */ #define _SC_ARG_MAX 1 #define _SC_CHILD_MAX 2 @@ -476,5 +477,6 @@ #define _SC_JOB_CONTROL 6 #define _SC_SAVED_IDS 7 #define _SC_VERSION 8 +#endif #endif /* _SPARC64_UNISTD_H */ diff -u --recursive --new-file v2.1.43/linux/include/linux/dalloc.h linux/include/linux/dalloc.h --- v2.1.43/linux/include/linux/dalloc.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/dalloc.h Sat Jul 5 23:12:35 1997 @@ -9,16 +9,19 @@ * . */ -#define D_MAXLEN 1024 +#define D_MAXLEN 1024 /* public flags for d_add() */ -#define D_NORMAL 0 -#define D_BASKET 1 /* put into basket (deleted/unref'd files) */ -#define D_DUPLICATE 2 /* allow duplicate entries */ -#define D_NOCHECKDUP 4 /* no not check for duplicates */ - -/* public flags for d_flag */ -#define D_PRELOADED 8 +#define D_NORMAL 0 +#define D_BASKET 1 /* put into basket (deleted/unref'd files) */ +#define D_DUPLICATE 2 /* allow duplicate entries */ +#define D_NOCHECKDUP 4 /* no not check for duplicates */ +#define D_NEGATIVE 8 /* negative entry */ +#define D_PRELOADED 16 +#define D_DIR 32 /* directory entry - look out for allocation issues */ +#define D_HASHED 64 +#define D_ZOMBIE 128 +#define D_INC_DDIR 512 /* public flags for d_del() */ #define D_REMOVE 0 @@ -26,31 +29,57 @@ #define IS_ROOT(x) ((x) == (x)->d_parent) +/* "quick string" -- I introduced this to shorten the parameter list + * of many routines. Think of it as a (str,stlen,hash) pair. + * Storing the len instead of doing strlen() very often is performance + * critical. + */ +struct qstr { + const unsigned char * name; + int len, hash; +}; + +/* Name hashing routines. Initial hash value */ +#define init_name_hash() 0 + +/* partial hash update function. Assume roughly 4 bits per character */ +static inline unsigned long partial_name_hash(unsigned char c, unsigned long prevhash) +{ + prevhash = (prevhash << 4) | (prevhash >> (8*sizeof(unsigned long)-4)); + return prevhash ^ c; +} + +/* Finally: cut down the number of bits to a int value (and try to avoid losing bits) */ +static inline unsigned long end_name_hash(unsigned long hash) +{ + if (sizeof(hash) > sizeof(unsigned int)) + hash += hash >> 4*sizeof(hash); + return (unsigned int) hash; +} + struct dentry { union { struct inode * d_inode; /* Where the name belongs to */ unsigned long d_ino; /* for preliminary entries */ } u; - struct dentry * d_parent; /* parent directory */ - struct dentry * d_next; /* hardlink aliasname / empty list */ - struct dentry * d_prev; /* hardlink aliasname */ + struct dentry * d_parent; /* parent directory */ + struct dentry * d_mounts; /* mount information */ + struct dentry * d_covers; + struct dentry * d_next; /* hardlink aliasname / empty list */ + struct dentry * d_prev; /* hardlink aliasname */ struct dentry * d_hash_next; struct dentry * d_hash_prev; struct dentry * d_basket_next; struct dentry * d_basket_prev; - short d_len; /* set by dalloc() */ - short d_flag; - char d_name[D_MAXLEN]; -}; -/* "quick string" -- I introduced this to shorten the parameter list - * of many routines. Think of it as a (str,stlen) pair. - * Storing the len instead of doing strlen() very often is performance - * critical. - */ -struct qstr { - const char * name; - int len; + /* Directory information */ + struct dentry * dd_basketlist; + struct dentry * dd_zombielist; + unsigned short dd_alloced; /* # d_alloc()ed, but not yet d_add()ed */ + unsigned short dd_hashed; /* # of entries in hashtable */ + + struct qstr d_name; + unsigned int d_flag; }; extern struct dentry * the_root; @@ -61,18 +90,18 @@ extern blocking struct inode * d_inode(struct dentry ** changing_entry); /* allocate proper space for the len */ -extern struct dentry * d_alloc(struct dentry * parent, int len, int isdir); +extern struct dentry * d_alloc(struct dentry * parent, struct qstr *name, int isdir); /* only used once at mount_root() */ extern blocking -struct dentry * d_alloc_root(struct inode * root_inode); +struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root); -/* d_inode is connected with inode, and d_name is copied from ininame. - * either of them may be NULL, but when ininame is NULL, dname must be - * set by the caller prior to calling this. */ +/* + * This adds the entry to the hash queues and initializes "d_inode". + * The entry was actually filled in earlier during "d_alloc()" + */ extern blocking -void d_add(struct dentry * entry, struct inode * inode, - struct qstr * ininame, int flags); +void d_add(struct dentry * entry, struct inode * inode, int flags); /* combination of d_alloc() and d_add(), less lookup overhead */ extern blocking @@ -86,17 +115,28 @@ /* used for rename() and baskets */ extern blocking -void d_move(struct dentry * entry, struct inode * newdir, - struct qstr * newname, struct qstr * newapp); +void d_move(struct dentry * entry, struct inode * newdir, struct qstr * newname); /* appendix may either be NULL or be used for transname suffixes */ -extern struct dentry * d_lookup(struct inode * dir, struct qstr * name, - struct qstr * appendix); +extern struct dentry * d_lookup(struct dentry * dir, struct qstr * name); /* write full pathname into buffer and return length */ -extern int d_path(struct dentry * entry, struct inode * chroot, char * buf); +extern int d_path(struct dentry * entry, struct dentry * chroot, char * buf); extern struct dentry * d_basket(struct dentry * dir_entry); extern int d_isbasket(struct dentry * entry); + +/* + * Wait for d_count.. + */ +#define dput(dentry) \ + iput((dentry)->u.d_inode) + +#define dget(d) ({ \ + struct dentry * __d = (d); \ + if (__d && __d->u.d_inode) \ + atomic_inc(&__d->u.d_inode->i_count); \ + __d; }) + #endif diff -u --recursive --new-file v2.1.43/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.1.43/linux/include/linux/ext2_fs.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/ext2_fs.h Tue Jul 1 15:24:14 1997 @@ -493,16 +493,14 @@ /* namei.c */ extern void ext2_release (struct inode *, struct file *); extern int ext2_lookup (struct inode *,const char *, int, struct inode **); -extern int ext2_create (struct inode *,const char *, int, int, - struct inode **); -extern int ext2_mkdir (struct inode *, const char *, int, int); -extern int ext2_rmdir (struct inode *, const char *, int); -extern int ext2_unlink (struct inode *, const char *, int); -extern int ext2_symlink (struct inode *, const char *, int, const char *); -extern int ext2_link (struct inode *, struct inode *, const char *, int); -extern int ext2_mknod (struct inode *, const char *, int, int, int); -extern int ext2_rename (struct inode *, const char *, int, - struct inode *, const char *, int); +extern int ext2_create (struct inode *,struct dentry *,int); +extern int ext2_mkdir (struct inode *,struct dentry *,int); +extern int ext2_rmdir (struct inode *,struct dentry *); +extern int ext2_unlink (struct inode *,struct dentry *); +extern int ext2_symlink (struct inode *,struct dentry *,const char *); +extern int ext2_link (struct inode *, struct inode *, struct dentry *); +extern int ext2_mknod (struct inode *, struct dentry *, int, int); +extern int ext2_rename (struct inode *, struct dentry *,struct inode *, struct dentry *); /* super.c */ extern void ext2_error (struct super_block *, const char *, const char *, ...) diff -u --recursive --new-file v2.1.43/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.43/linux/include/linux/fs.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/fs.h Sat Jul 5 20:53:22 1997 @@ -15,13 +15,17 @@ #include #include #include + #include +#include /* Prefixes for routines (having no effect), but indicate what * the routine may do. This can greatly ease reasoning about routines... */ #define blocking /*routine may schedule()*/ +#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 @@ -104,13 +108,6 @@ #define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ /* - * Public flags for namei() - */ -#define NAM_PLAIN 0 /* Retrieve last component of pathname as is. */ -#define NAM_FOLLOW_LINK 2 /* If last component of path is a symlink, follow it */ -#define NAM_FOLLOW_TRAILSLASH 4 /* Follow last symlink only if trailed by slash. */ - -/* * Note that read-only etc flags are inode-specific: setting some file-system * flags just means all the inodes inherit those flags by default. It might be * possible to override it selectively if you really wanted to with some @@ -183,18 +180,16 @@ */ struct buffer_head { /* First cache line: */ + struct buffer_head * b_next; /* Hash queue list */ unsigned long b_blocknr; /* block number */ + unsigned long b_size; /* block size */ kdev_t b_dev; /* device (B_FREE = free) */ kdev_t b_rdev; /* Real device */ unsigned long b_rsector; /* Real buffer location on disk */ - struct buffer_head * b_next; /* Hash queue list */ struct buffer_head * b_this_page; /* circular list of buffers in one page */ - - /* Second cache line: */ unsigned long b_state; /* buffer state bitmap (see above) */ struct buffer_head * b_next_free; unsigned int b_count; /* users using this block */ - unsigned long b_size; /* block size */ /* Non-performance-critical data follows. */ char * b_data; /* pointer to data block (1024 bytes) */ @@ -347,7 +342,6 @@ unsigned short i_status; unsigned short i_reuse_count; - struct inode *i_mount; unsigned int i_flags; unsigned char i_lock; unsigned char i_dirt; @@ -503,8 +497,7 @@ unsigned long s_flags; unsigned long s_magic; unsigned long s_time; - struct inode *s_covered; - struct inode *s_mounted; + struct dentry *s_root; struct wait_queue *s_wait; struct inode *s_ibasket; @@ -553,16 +546,17 @@ struct inode_operations { struct file_operations * default_file_ops; - int (*create) (struct inode *,const char *,int,int,struct inode **); + int (*create) (struct inode *,struct dentry *,int); int (*lookup) (struct inode *,const char *,int,struct inode **); - int (*link) (struct inode *,struct inode *,const char *,int); - int (*unlink) (struct inode *,const char *,int); - int (*symlink) (struct inode *,const char *,int,const char *); - int (*mkdir) (struct inode *,const char *,int,int); - int (*rmdir) (struct inode *,const char *,int); - int (*mknod) (struct inode *,const char *,int,int,int); - int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int); + int (*link) (struct inode *,struct inode *,struct dentry *); + int (*unlink) (struct inode *,struct dentry *); + int (*symlink) (struct inode *,struct dentry *,const char *); + int (*mkdir) (struct inode *,struct dentry *,int); + int (*rmdir) (struct inode *,struct dentry *); + int (*mknod) (struct inode *,struct dentry *,int,int); + int (*rename) (struct inode *,struct dentry *,struct inode *,struct dentry *); int (*readlink) (struct inode *,char *,int); + struct dentry * (*follow_link) (struct inode *, struct dentry *); int (*readpage) (struct inode *, struct page *); int (*writepage) (struct inode *, struct page *); int (*bmap) (struct inode *,int); @@ -640,7 +634,7 @@ extern struct file_system_type *get_fs_type(const char *name); extern int fs_may_mount(kdev_t dev); -extern int fs_may_umount(kdev_t dev, struct inode * mount_root); +extern int fs_may_umount(kdev_t dev, struct dentry * root); extern int fs_may_remount_ro(kdev_t dev); extern struct file *inuse_filps; @@ -689,15 +683,32 @@ extern void sync_supers(kdev_t dev); extern int bmap(struct inode * inode,int block); extern int notify_change(struct inode *, struct iattr *); -extern int namei(int retr_mode, const char *pathname, struct inode **res_inode); extern int permission(struct inode * inode,int mask); extern int get_write_access(struct inode *inode); extern void put_write_access(struct inode *inode); extern int open_namei(const char * pathname, int flag, int mode, - struct inode ** res_inode, struct inode * base); + struct inode ** res_inode, struct dentry * base); extern int do_mknod(const char * filename, int mode, dev_t dev); extern int do_pipe(int *); +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ +#define ERR_PTR(err) ((void *)((long)(err))) +#define PTR_ERR(ptr) ((long)(ptr)) +#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +extern struct dentry * lookup_dentry(const char *, struct dentry *, int); +extern int __namei(const char *, struct inode **, int); + +#define namei(pathname, inode_p) __namei(pathname, inode_p, 1) +#define lnamei(pathname, inode_p) __namei(pathname, inode_p, 0) + #include /* Intended for short locks of the global data structures in inode.c. @@ -748,7 +759,7 @@ */ extern inline void iinc_zero(struct inode * inode) { - if(!atomic_read(&inode->i_count)) { + if (!atomic_read(&inode->i_count)) { atomic_inc(&inode->i_count); _get_inode(inode); } else @@ -758,21 +769,21 @@ extern blocking void _iput(struct inode * inode); extern inline blocking void iput(struct inode * inode) { - if(inode) { + if (inode) { extern void wake_up_interruptible(struct wait_queue **q); - if(inode->i_pipe) + if( inode->i_pipe) wake_up_interruptible(&inode->u.pipe_i.wait); /* It does not matter if somebody re-increments it in between, * only the _last_ user needs to call _iput(). */ - if(atomic_dec_and_test(&inode->i_count) && inode->i_ddir_count <= 0) + if (atomic_dec_and_test(&inode->i_count) && inode->i_ddir_count <= 0) _iput(inode); } } -extern blocking struct inode * __iget(struct super_block * sb, unsigned long nr, int crsmnt); +extern blocking struct inode * iget(struct super_block * sb, unsigned long nr); extern blocking void _clear_inode(struct inode * inode, int external, int verbose); extern blocking inline void clear_inode(struct inode * inode) { @@ -795,9 +806,9 @@ */ blocking struct inode * get_empty_inode_hashed(dev_t i_dev, unsigned long i_ino); +extern blocking int _free_ibasket(struct super_block * sb); extern inline blocking int free_ibasket(struct super_block * sb) { - extern blocking int _free_ibasket(struct super_block * sb); int res; vfs_lock(); res = _free_ibasket(sb); @@ -871,12 +882,6 @@ extern int inode_change_ok(struct inode *, struct iattr *); extern void inode_setattr(struct inode *, struct iattr *); - -extern inline blocking -struct inode * iget(struct super_block * sb, unsigned long nr) -{ - return __iget(sb, nr, 1); -} /* kludge to get SCSI modules working */ #include diff -u --recursive --new-file v2.1.43/linux/include/linux/if_arp.h linux/include/linux/if_arp.h --- v2.1.43/linux/include/linux/if_arp.h Thu Jun 12 15:29:21 1997 +++ linux/include/linux/if_arp.h Thu Jul 3 17:43:31 1997 @@ -47,6 +47,8 @@ #define ARPHRD_ROSE 270 #define ARPHRD_X25 271 /* CCITT X.25 */ #define ARPHRD_PPP 512 +#define ARPHRD_HDLC 513 /* (Cisco) HDLC */ +#define ARPHRD_LAPB 516 /* LAPB */ #define ARPHRD_TUNNEL 768 /* IPIP tunnel */ #define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */ diff -u --recursive --new-file v2.1.43/linux/include/linux/net.h linux/include/linux/net.h --- v2.1.43/linux/include/linux/net.h Thu Jun 12 15:28:32 1997 +++ linux/include/linux/net.h Thu Jun 26 12:33:40 1997 @@ -136,5 +136,8 @@ extern int sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags); extern int sock_readv_writev(int type, struct inode * inode, struct file * file, const struct iovec * iov, long count, long size); + +int net_ratelimit(void); + #endif /* __KERNEL__ */ #endif /* _LINUX_NET_H */ diff -u --recursive --new-file v2.1.43/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.43/linux/include/linux/pci.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/pci.h Thu Jun 26 12:33:40 1997 @@ -497,7 +497,7 @@ #define PCI_DEVICE_ID_VIA_82C586_1 0x0571 #define PCI_DEVICE_ID_VIA_82C576 0x0576 #define PCI_DEVICE_ID_VIA_82C585 0x0585 -#define PCI_DEVICE_ID_VIA_82C586_0 0x0586 +#define PCI_DEVICE_ID_VIA_82C586 0x0586 #define PCI_DEVICE_ID_VIA_82C416 0x1571 #define PCI_VENDOR_ID_VORTEX 0x1119 diff -u --recursive --new-file v2.1.43/linux/include/linux/random.h linux/include/linux/random.h --- v2.1.43/linux/include/linux/random.h Thu Jun 6 03:42:15 1996 +++ linux/include/linux/random.h Thu Jun 26 12:33:40 1997 @@ -55,6 +55,8 @@ extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport); +extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, + __u16 sport, __u16 dport, __u32 sseq, __u32 count); #ifndef MODULE extern struct file_operations random_fops, urandom_fops; diff -u --recursive --new-file v2.1.43/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.43/linux/include/linux/sched.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/sched.h Thu Jul 3 17:41:49 1997 @@ -130,7 +130,7 @@ struct fs_struct { int count; int umask; - struct inode * root, * pwd; + struct dentry * root, * pwd; }; #define INIT_FS { \ @@ -519,12 +519,10 @@ { struct wait_queue * next = wait->next; struct wait_queue * head = next; + struct wait_queue * tmp; - for (;;) { - struct wait_queue * nextlist = head->next; - if (nextlist == wait) - break; - head = nextlist; + while ((tmp = head->next) != wait) { + head = tmp; } head->next = next; } diff -u --recursive --new-file v2.1.43/linux/include/linux/slab.h linux/include/linux/slab.h --- v2.1.43/linux/include/linux/slab.h Thu Jun 12 15:28:33 1997 +++ linux/include/linux/slab.h Thu Jul 3 17:41:50 1997 @@ -32,7 +32,7 @@ #define SLAB_DEBUG_FREE 0x00000100UL /* Peform (expensive) checks on free */ #define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */ #define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */ -#define SLAB_POISION 0x00000800UL /* Poision objects */ +#define SLAB_POISON 0x00000800UL /* Poison objects */ #define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */ #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */ #if 0 @@ -56,7 +56,7 @@ extern void kmem_cache_free(kmem_cache_t *, void *); extern void *kmalloc(size_t, int); -extern void kfree(void *); +extern void kfree(const void *); extern void kfree_s(void *, size_t); extern int kmem_cache_reap(int, int, int); diff -u --recursive --new-file v2.1.43/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.1.43/linux/include/linux/sysctl.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/sysctl.h Thu Jun 26 12:33:40 1997 @@ -173,6 +173,7 @@ NET_IPV4_IGMP_AGE_THRESHOLD, NET_TCP_SYNCOOKIES, NET_TCP_ALWAYS_SYNCOOKIE, + NET_TCP_STDURG, }; diff -u --recursive --new-file v2.1.43/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.43/linux/include/linux/tty.h Thu Jun 12 15:28:33 1997 +++ linux/include/linux/tty.h Thu Jul 3 17:41:49 1997 @@ -90,13 +90,19 @@ struct tty_flip_buffer { struct tq_struct tqueue; - unsigned char char_buf[2*TTY_FLIPBUF_SIZE]; - char flag_buf[2*TTY_FLIPBUF_SIZE]; + struct semaphore pty_sem; char *char_buf_ptr; unsigned char *flag_buf_ptr; int count; int buf_num; + unsigned char char_buf[2*TTY_FLIPBUF_SIZE]; + char flag_buf[2*TTY_FLIPBUF_SIZE]; + unsigned char slop[4]; /* N.B. bug overwrites buffer by 1 */ }; +/* + * The pty uses char_buf and flag_buf as a contiguous buffer + */ +#define PTY_BUF_SIZE 4*TTY_FLIPBUF_SIZE /* * When a break, frame error, or parity error happens, these codes are @@ -198,7 +204,7 @@ * most often used by a windowing system, which will set the correct * size each time the window is created or resized anyway. * IMPORTANT: since this structure is dynamically allocated, it must - * be no larger than 4096 bytes. Changing TTY_BUF_SIZE will change + * be no larger than 4096 bytes. Changing TTY_FLIPBUF_SIZE will change * the size of this structure, and it needs to be done with care. * - TYT, 9/14/92 */ diff -u --recursive --new-file v2.1.43/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.43/linux/include/net/tcp.h Thu Jun 12 15:31:03 1997 +++ linux/include/net/tcp.h Thu Jul 3 17:44:41 1997 @@ -281,15 +281,17 @@ int (*conn_request) (struct sock *sk, struct sk_buff *skb, - void *opt, - __u32 isn); + void *opt, __u32 isn); struct sock * (*syn_recv_sock) (struct sock *sk, struct sk_buff *skb, - struct open_request *req); + struct open_request *req, + struct dst_entry *dst); +#if 0 __u32 (*init_sequence) (struct sock *sk, struct sk_buff *skb); +#endif struct sock * (*get_sock) (struct sk_buff *skb, struct tcphdr *th); @@ -385,7 +387,8 @@ int len, int nonblock, int flags, int *addr_len); -extern void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp); +extern void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, + int no_fancy); /* * TCP v4 functions exported for the inet6 API @@ -407,7 +410,8 @@ extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, - struct open_request *req); + struct open_request *req, + struct dst_entry *dst); extern int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb); @@ -417,6 +421,12 @@ int addr_len); +/* From syncookies.c */ +extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, + struct ip_options *opt); +extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, + __u16 *mss); + extern void tcp_read_wakeup(struct sock *); extern void tcp_write_xmit(struct sock *); extern void tcp_time_wait(struct sock *); @@ -521,7 +531,6 @@ { return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base); } - #undef STATE_TRACE diff -u --recursive --new-file v2.1.43/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.43/linux/kernel/exit.c Mon Jun 16 16:36:01 1997 +++ linux/kernel/exit.c Tue Jul 1 14:19:02 1997 @@ -404,8 +404,8 @@ if (fs) { tsk->fs = NULL; if (!--fs->count) { - iput(fs->root); - iput(fs->pwd); + dput(fs->root); + dput(fs->pwd); kfree(fs); } } diff -u --recursive --new-file v2.1.43/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.43/linux/kernel/fork.c Mon Jun 16 16:36:01 1997 +++ linux/kernel/fork.c Sat Jul 5 20:53:22 1997 @@ -302,10 +302,8 @@ return -1; tsk->fs->count = 1; tsk->fs->umask = current->fs->umask; - if ((tsk->fs->root = current->fs->root)) - atomic_inc(&tsk->fs->root->i_count); - if ((tsk->fs->pwd = current->fs->pwd)) - atomic_inc(&tsk->fs->pwd->i_count); + tsk->fs->root = dget(current->fs->root); + tsk->fs->pwd = dget(current->fs->pwd); return 0; } diff -u --recursive --new-file v2.1.43/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.43/linux/kernel/ksyms.c Mon Jun 16 16:36:01 1997 +++ linux/kernel/ksyms.c Thu Jul 3 17:42:27 1997 @@ -141,9 +141,10 @@ EXPORT_SYMBOL(getname); EXPORT_SYMBOL(putname); EXPORT_SYMBOL(__fput); -EXPORT_SYMBOL(__iget); +EXPORT_SYMBOL(iget); EXPORT_SYMBOL(_iput); -EXPORT_SYMBOL(namei); +EXPORT_SYMBOL(__namei); +EXPORT_SYMBOL(lookup_dentry); EXPORT_SYMBOL(open_namei); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(close_fp); @@ -341,6 +342,7 @@ EXPORT_SYMBOL(sys_tz); EXPORT_SYMBOL(__wait_on_super); EXPORT_SYMBOL(file_fsync); +EXPORT_SYMBOL(_free_ibasket); EXPORT_SYMBOL(_clear_inode); EXPORT_SYMBOL(refile_buffer); EXPORT_SYMBOL(nr_async_pages); diff -u --recursive --new-file v2.1.43/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.43/linux/kernel/sys.c Mon Jun 16 16:36:01 1997 +++ linux/kernel/sys.c Thu Jun 26 12:33:40 1997 @@ -612,21 +612,17 @@ */ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) { - uid_t old_ruid, old_euid, old_suid; - - old_ruid = current->uid; - old_euid = current->euid; - old_suid = current->suid; - - if ((ruid != (uid_t) -1) && (ruid != current->uid) && - (ruid != current->euid) && (ruid != current->suid)) - return -EPERM; - if ((euid != (uid_t) -1) && (euid != current->uid) && - (euid != current->euid) && (euid != current->suid)) - return -EPERM; - if ((suid != (uid_t) -1) && (suid != current->uid) && - (suid != current->euid) && (suid != current->suid)) - return -EPERM; + if (current->uid != 0 && current->euid != 0 && current->suid != 0) { + if ((ruid != (uid_t) -1) && (ruid != current->uid) && + (ruid != current->euid) && (ruid != current->suid)) + return -EPERM; + if ((euid != (uid_t) -1) && (euid != current->uid) && + (euid != current->euid) && (euid != current->suid)) + return -EPERM; + if ((suid != (uid_t) -1) && (suid != current->uid) && + (suid != current->euid) && (suid != current->suid)) + return -EPERM; + } if (ruid != (uid_t) -1) { /* See above commentary about NPROC rlimit issues here. */ charge_uid(current, -1); @@ -634,8 +630,12 @@ if(ruid) charge_uid(current, 1); } - if (euid != (uid_t) -1) + if (euid != (uid_t) -1) { + if (euid != current->euid) + current->dumpable = 0; current->euid = euid; + current->fsuid = euid; + } if (suid != (uid_t) -1) current->suid = suid; return 0; @@ -648,6 +648,46 @@ if (!(retval = put_user(current->uid, ruid)) && !(retval = put_user(current->euid, euid))) retval = put_user(current->suid, suid); + + return retval; +} + +/* + * Same as above, but for rgid, egid, sgid. + */ +asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) +{ + if (current->uid != 0 && current->euid != 0 && current->suid != 0) { + if ((rgid != (gid_t) -1) && (rgid != current->gid) && + (rgid != current->egid) && (rgid != current->sgid)) + return -EPERM; + if ((egid != (gid_t) -1) && (egid != current->gid) && + (egid != current->egid) && (egid != current->sgid)) + return -EPERM; + if ((sgid != (gid_t) -1) && (sgid != current->gid) && + (sgid != current->egid) && (sgid != current->sgid)) + return -EPERM; + } + if (rgid != (gid_t) -1) + current->gid = rgid; + if (egid != (gid_t) -1) { + if (egid != current->egid) + current->dumpable = 0; + current->egid = egid; + current->fsgid = egid; + } + if (sgid != (gid_t) -1) + current->sgid = sgid; + return 0; +} + +asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) +{ + int retval; + + if (!(retval = put_user(current->gid, rgid)) && + !(retval = put_user(current->egid, egid))) + retval = put_user(current->sgid, sgid); return retval; } diff -u --recursive --new-file v2.1.43/linux/mm/slab.c linux/mm/slab.c --- v2.1.43/linux/mm/slab.c Mon Jun 16 16:36:01 1997 +++ linux/mm/slab.c Tue Jul 1 17:30:40 1997 @@ -123,7 +123,7 @@ * 0 if you wish to reduce memory usage. * * SLAB_DEBUG_SUPPORT - 1 for kmem_cache_create() to honour; SLAB_DEBUG_FREE, - * SLAB_DEBUG_INITIAL, SLAB_RED_ZONE & SLAB_POISION. + * SLAB_DEBUG_INITIAL, SLAB_RED_ZONE & SLAB_POISON. * 0 for faster, smaller, code (espically in the critical paths). * * SLAB_STATS - 1 to collect stats for /proc/slabinfo. @@ -143,11 +143,11 @@ #if SLAB_DEBUG_SUPPORT #if 0 #define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \ - SLAB_POISION|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP| \ + SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP| \ SLAB_HIGH_PACK) #endif #define SLAB_C_MASK (SLAB_DEBUG_FREE|SLAB_DEBUG_INITIAL|SLAB_RED_ZONE| \ - SLAB_POISION|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP) + SLAB_POISON|SLAB_HWCACHE_ALIGN|SLAB_NO_REAP) #else #if 0 #define SLAB_C_MASK (SLAB_HWCACHE_ALIGN|SLAB_NO_REAP|SLAB_HIGH_PACK) @@ -215,9 +215,9 @@ #define SLAB_RED_MAGIC1 0x5A2CF071UL /* when obj is active */ #define SLAB_RED_MAGIC2 0x170FC2A5UL /* when obj is inactive */ -/* ...and for poisioning */ -#define SLAB_POISION_BYTE 0x5a /* byte value for poisioning */ -#define SLAB_POISION_END 0xa5 /* end-byte of poisioning */ +/* ...and for poisoning */ +#define SLAB_POISON_BYTE 0x5a /* byte value for poisoning */ +#define SLAB_POISON_END 0xa5 /* end-byte of poisoning */ #endif /* SLAB_DEBUG_SUPPORT */ @@ -546,17 +546,17 @@ #if SLAB_DEBUG_SUPPORT static inline void -kmem_poision_obj(kmem_cache_t *cachep, void *addr) +kmem_poison_obj(kmem_cache_t *cachep, void *addr) { - memset(addr, SLAB_POISION_BYTE, cachep->c_org_size); - *(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISION_END; + memset(addr, SLAB_POISON_BYTE, cachep->c_org_size); + *(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISON_END; } static inline int -kmem_check_poision_obj(kmem_cache_t *cachep, void *addr) +kmem_check_poison_obj(kmem_cache_t *cachep, void *addr) { void *end; - end = memchr(addr, SLAB_POISION_END, cachep->c_org_size); + end = memchr(addr, SLAB_POISON_END, cachep->c_org_size); if (end != (addr+cachep->c_org_size-1)) return 1; return 0; @@ -605,7 +605,7 @@ { if (cachep->c_dtor #if SLAB_DEBUG_SUPPORT - || cachep->c_flags & (SLAB_POISION || SLAB_RED_ZONE) + || cachep->c_flags & (SLAB_POISON || SLAB_RED_ZONE) #endif /*SLAB_DEBUG_SUPPORT*/ ) { /* Doesn't use the bufctl ptrs to find objs. */ @@ -629,10 +629,10 @@ #endif /*SLAB_DEBUG_SUPPORT*/ (cachep->c_dtor)(objp, cachep, 0); #if SLAB_DEBUG_SUPPORT - else if (cachep->c_flags & SLAB_POISION) { - if (kmem_check_poision_obj(cachep, objp)) + else if (cachep->c_flags & SLAB_POISON) { + if (kmem_check_poison_obj(cachep, objp)) printk(KERN_ERR "kmem_slab_destory: " - "Bad poision - %s\n", cachep->c_name); + "Bad poison - %s\n", cachep->c_name); } if (cachep->c_flags & SLAB_RED_ZONE) objp -= BYTES_PER_WORD; @@ -726,18 +726,18 @@ flags &= ~SLAB_DEBUG_INITIAL; } - if ((flags & SLAB_POISION) && ctor) { - /* request for poisioning, but we can't do that with a constructor */ - printk("%sPoisioning requested, but con given - %s\n", func_nm, name); - flags &= ~SLAB_POISION; + if ((flags & SLAB_POISON) && ctor) { + /* request for poisoning, but we can't do that with a constructor */ + printk("%sPoisoning requested, but con given - %s\n", func_nm, name); + flags &= ~SLAB_POISON; } #if 0 if ((flags & SLAB_HIGH_PACK) && ctor) { printk("%sHigh pack requested, but con given - %s\n", func_nm, name); flags &= ~SLAB_HIGH_PACK; } - if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISION|SLAB_RED_ZONE))) { - printk("%sHigh pack requested, but with poisioning/red-zoning - %s\n", + if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISON|SLAB_RED_ZONE))) { + printk("%sHigh pack requested, but with poisoning/red-zoning - %s\n", func_nm, name); flags &= ~SLAB_HIGH_PACK; } @@ -1094,9 +1094,9 @@ if (cachep->c_ctor) cachep->c_ctor(objp, cachep, ctor_flags); #if SLAB_DEBUG_SUPPORT - else if (cachep->c_flags & SLAB_POISION) { - /* need to poision the objs */ - kmem_poision_obj(cachep, objp); + else if (cachep->c_flags & SLAB_POISON) { + /* need to poison the objs */ + kmem_poison_obj(cachep, objp); } if (cachep->c_flags & SLAB_RED_ZONE) { @@ -1386,7 +1386,7 @@ bufp->buf_slabp = slabp; objp = ((void*)bufp) - cachep->c_offset; finished: - /* The lock is not needed by the red-zone or poision ops, and the + /* The lock is not needed by the red-zone or poison ops, and the * obj has been removed from the slab. Should be safe to drop * the lock here. */ @@ -1395,8 +1395,8 @@ if (cachep->c_flags & SLAB_RED_ZONE) goto red_zone; ret_red: - if ((cachep->c_flags & SLAB_POISION) && kmem_check_poision_obj(cachep, objp)) - kmem_report_alloc_err("Bad poision", cachep); + if ((cachep->c_flags & SLAB_POISON) && kmem_check_poison_obj(cachep, objp)) + kmem_report_alloc_err("Bad poison", cachep); #endif /* SLAB_DEBUG_SUPPORT */ return objp; } @@ -1514,10 +1514,10 @@ /* (hopefully) The most common case. */ finished: #if SLAB_DEBUG_SUPPORT - if (cachep->c_flags & SLAB_POISION) { + if (cachep->c_flags & SLAB_POISON) { if (cachep->c_flags & SLAB_RED_ZONE) objp += BYTES_PER_WORD; - kmem_poision_obj(cachep, objp); + kmem_poison_obj(cachep, objp); } #endif /* SLAB_DEBUG_SUPPORT */ spin_unlock_irqrestore(&cachep->c_spinlock, save_flags); @@ -1615,7 +1615,7 @@ } void -kfree(void *objp) +kfree(const void *objp) { struct page *page; int nr; @@ -1860,7 +1860,7 @@ kmem_cache_t *test_cachep; printk(KERN_INFO "kmem_test() - start\n"); - test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISION, NULL, NULL); + test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISON, NULL, NULL); if (test_cachep) { char *objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL); if (objp) { @@ -1869,12 +1869,12 @@ *(objp+16) = 1; kmem_cache_free(test_cachep, objp); - /* Mess up poisioning. */ + /* Mess up poisoning. */ *objp = 10; objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL); kmem_cache_free(test_cachep, objp); - /* Mess up poisioning (again). */ + /* Mess up poisoning (again). */ *objp = 10; kmem_cache_shrink(test_cachep); } diff -u --recursive --new-file v2.1.43/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.1.43/linux/mm/swapfile.c Mon Jun 16 16:36:01 1997 +++ linux/mm/swapfile.c Tue Jul 1 14:25:59 1997 @@ -334,7 +334,7 @@ lock_kernel(); if (!suser()) goto out; - err = namei(NAM_FOLLOW_LINK, specialfile, &inode); + err = namei(specialfile, &inode); if (err) goto out; prev = -1; @@ -488,7 +488,7 @@ } else { p->prio = --least_priority; } - error = namei(NAM_FOLLOW_LINK, specialfile, &swap_inode); + error = namei(specialfile, &swap_inode); if (error) goto bad_swap_2; p->swap_file = swap_inode; diff -u --recursive --new-file v2.1.43/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.1.43/linux/net/appletalk/ddp.c Mon Jun 16 16:36:01 1997 +++ linux/net/appletalk/ddp.c Thu Jun 26 12:33:40 1997 @@ -1540,11 +1540,33 @@ ddp_dl->header_length + ddp->deh_len)); *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* Mend the byte order */ + /* * Send the buffer onwards */ - skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ); + /* + * Now we must always be careful. If it's come from + * localtalk to ethertalk it might not fit + * + * Order matters here: If a packet has to be copied + * to make a new headroom (rare hopefully) then it + * won't need unsharing. + * + * Note. ddp-> becomes invalid at the realloc. + */ + + if(skb_headroom(skb)<22) + /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ + skb=skb_realloc_headroom(skb, 32); + else + skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ); + + /* + * If the buffer didnt vanish into the lack of + * space bitbucket we can send it. + */ + if(skb) { skb->arp = 1; /* Resolved */ @@ -1702,10 +1724,14 @@ return(-EINVAL); if(usat->sat_family != AF_APPLETALK) return -EINVAL; -#if 0 /* netatalk doesn't implement this check */ + /* netatalk doesn't implement this check */ if(usat->sat_addr.s_node==ATADDR_BCAST && !sk->broadcast) + { + printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as it will break before 2.2\n"); +#if 0 return -EPERM; #endif + } } else { diff -u --recursive --new-file v2.1.43/linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- v2.1.43/linux/net/ipv4/Config.in Fri Feb 7 05:54:55 1997 +++ linux/net/ipv4/Config.in Thu Jun 26 12:33:41 1997 @@ -31,6 +31,7 @@ bool 'IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD fi fi +bool 'IP: TCP syncookie support (not enabled per default) ' CONFIG_SYN_COOKIES comment '(it is safe to leave these untouched)' bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP tristate 'IP: Reverse ARP' CONFIG_INET_RARP diff -u --recursive --new-file v2.1.43/linux/net/ipv4/Makefile linux/net/ipv4/Makefile --- v2.1.43/linux/net/ipv4/Makefile Thu Mar 27 14:40:15 1997 +++ linux/net/ipv4/Makefile Thu Jun 26 12:33:41 1997 @@ -52,6 +52,11 @@ endif endif +ifeq ($(CONFIG_SYN_COOKIES),y) +IPV4_OBJS += syncookies.o +# module not supported, because it would be too messy. +endif + ifdef CONFIG_INET O_OBJS := $(IPV4_OBJS) OX_OBJS := $(IPV4X_OBJS) diff -u --recursive --new-file v2.1.43/linux/net/ipv4/raw.c linux/net/ipv4/raw.c --- v2.1.43/linux/net/ipv4/raw.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/raw.c Thu Jun 26 12:33:41 1997 @@ -388,7 +388,7 @@ err = memcpy_fromiovec(buf, msg->msg_iov, len); if (!err) { - unsigned short fs; + unsigned long fs; fs=get_fs(); set_fs(get_ds()); err=raw_sendto(sk,buf,len, msg); diff -u --recursive --new-file v2.1.43/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.1.43/linux/net/ipv4/route.c Tue May 13 22:41:23 1997 +++ linux/net/ipv4/route.c Thu Jun 26 12:33:41 1997 @@ -45,6 +45,7 @@ * Pavel Krauz : Limited broadcast fixed * Alexey Kuznetsov : End of old history. Splitted to fib.c and * route.c and rewritten from scratch. + * Andi Kleen : Load-limit warning messages. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -568,7 +569,7 @@ return; reject_redirect: - if (ipv4_config.log_martians) + if (ipv4_config.log_martians && net_ratelimit()) printk(KERN_INFO "Redirect from %lX/%s to %lX ignored." "Path = %lX -> %lX, tos %02x\n", ntohl(old_gw), dev->name, ntohl(new_gw), @@ -636,7 +637,7 @@ if (jiffies - rt->last_error > (RT_REDIRECT_LOAD<errors)) { icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); rt->last_error = jiffies; - if (ipv4_config.log_martians && ++rt->errors == RT_REDIRECT_NUMBER) + if (ipv4_config.log_martians && ++rt->errors == RT_REDIRECT_NUMBER && net_ratelimit()) printk(KERN_WARNING "host %08x/%s ignores redirects for %08x to %08x.\n", rt->rt_src, rt->rt_src_dev->name, rt->rt_dst, rt->rt_gateway); } @@ -1083,12 +1084,12 @@ * Do not cache martian addresses: they should be logged (RFC1812) */ martian_destination: - if (ipv4_config.log_martians) + if (ipv4_config.log_martians && net_ratelimit()) printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name); return -EINVAL; martian_source: - if (ipv4_config.log_martians) { + if (ipv4_config.log_martians && net_ratelimit()) { /* * RFC1812 recommenadtion, if source is martian, * the only hint is MAC header. diff -u --recursive --new-file v2.1.43/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c --- v2.1.43/linux/net/ipv4/syncookies.c Wed Dec 31 16:00:00 1969 +++ linux/net/ipv4/syncookies.c Thu Jun 26 12:33:41 1997 @@ -0,0 +1,218 @@ +/* + * Syncookies implementation for the Linux kernel + * + * Copyright (C) 1997 Andi Kleen + * Based on ideas by D.J.Bernstein and Eric Schenk. + * + * 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. + * + * $Id: syncookies.c,v 1.1 1997/06/06 20:37:56 freitag Exp $ + * + * Missing: IPv6 support. + * Some counter so that the Administrator can see when the machine + * is under a syn flood attack. + */ + +#include +#if defined(CONFIG_SYN_COOKIES) +#include +#include +#include +#include + +extern int sysctl_tcp_syncookies; + +static unsigned long tcp_lastsynq_overflow; + +/* + * This table has to be sorted. Only 8 entries are allowed and the + * last entry has to be duplicated. + * XXX generate a better table. + * Unresolved Issues: HIPPI with a 64k MSS is not well supported. + */ +static __u16 const msstab[] = { + 64, + 256, + 512, + 536, + 1024, + 1440, + 1460, + 4312, + 4312 +}; + +static __u32 make_syncookie(struct sk_buff *skb, __u32 counter, __u32 seq) +{ + __u32 z; + + z = secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr, + skb->h.th->source, skb->h.th->dest, + seq, + counter); + +#if 0 + printk(KERN_DEBUG + "msc: z=%u,cnt=%u,seq=%u,sadr=%u,dadr=%u,sp=%u,dp=%u\n", + z,counter,seq, + skb->nh.iph->saddr,skb->nh.iph->daddr, + ntohs(skb->h.th->source), ntohs(skb->h.th->dest)); +#endif + + return z; +} + +/* + * Generate a syncookie. + */ +__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, + __u16 *mssp) +{ + int i; + __u32 isn; + const __u16 mss = *mssp, *w; + + tcp_lastsynq_overflow = jiffies; + + isn = make_syncookie(skb, (jiffies/HZ) >> 6, ntohl(skb->h.th->seq)); + + /* XXX sort msstab[] by probability? */ + w = msstab; + for (i = 0; i < 8; i++) + if (mss >= *w && mss < *++w) + goto found; + i--; +found: + *mssp = w[-1]; + + isn |= i; + return isn; +} + +/* This value should be dependant on TCP_TIMEOUT_INIT and + * sysctl_tcp_retries1. It's a rather complicated formula + * (exponential backoff) to compute at runtime so it's currently hardcoded + * here. + */ +#define COUNTER_TRIES 4 + +/* + * Check if a ack sequence number is a valid syncookie. + */ +static inline int cookie_check(struct sk_buff *skb, __u32 cookie) +{ + int mssind; + int i; + __u32 counter; + __u32 seq; + + if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT + && tcp_lastsynq_overflow) + return 0; + + mssind = cookie & 7; + cookie &= ~7; + + counter = (jiffies/HZ)>>6; + seq = ntohl(skb->h.th->seq)-1; + for (i = 0; i < COUNTER_TRIES; i++) + if (make_syncookie(skb, counter-i, seq) == cookie) + return msstab[mssind]; + + return 0; +} + +extern struct or_calltable or_ipv4; + +static inline struct sock * +get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req, + struct dst_entry *dst) +{ + struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + + sk = tp->af_specific->syn_recv_sock(sk, skb, req, dst); + req->sk = sk; + + /* Queue up for accept() */ + tcp_synq_queue(tp, req); + + return sk; +} + +struct sock * +cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt) +{ + __u32 cookie = ntohl(skb->h.th->ack_seq)-1; + struct open_request *req; + int mss; + struct rtable *rt; + + if (!sysctl_tcp_syncookies) + return sk; + if (!skb->h.th->ack) + return sk; + + mss = cookie_check(skb, cookie); + if (mss == 0) + return sk; + + req = tcp_openreq_alloc(); + if (req == NULL) + return NULL; + + req->rcv_isn = htonl(skb->h.th->seq)-1; + req->snt_isn = cookie; + req->mss = mss; + req->rmt_port = skb->h.th->source; + req->af.v4_req.loc_addr = skb->nh.iph->daddr; + req->af.v4_req.rmt_addr = skb->nh.iph->saddr; + req->class = &or_ipv4; /* for savety */ + + /* We throwed the options of the initial SYN away, so we hope + * the ACK carries the same options again (see RFC1122 4.2.3.8) + */ + if (opt && opt->optlen) { + int opt_size = sizeof(struct ip_options) + opt->optlen; + + req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); + if (req->af.v4_req.opt) { + if (ip_options_echo(req->af.v4_req.opt, skb)) { + kfree_s(req->af.v4_req.opt, opt_size); + req->af.v4_req.opt = NULL; + } + } + } + + req->af.v4_req.opt = NULL; + req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0; + req->wscale_ok = 0; + req->expires = 0UL; + req->retrans = 0; + + /* + * We need to lookup the route here to get at the correct + * window size. We should better make sure that the window size + * hasn't changed since we received the original syn, but I see + * no easy way to do this. + */ + if (ip_route_output(&rt, + opt && opt->srr ? opt->faddr : + req->af.v4_req.rmt_addr,req->af.v4_req.loc_addr, + sk->ip_tos, NULL)) { + tcp_openreq_free(req); + return NULL; + } + + /* Try to redo what tcp_v4_send_synack did. */ + req->window_clamp = rt->u.dst.window; + tcp_select_initial_window(sock_rspace(sk)/2,req->mss, + &req->rcv_wnd, &req->window_clamp, + 0, &req->rcv_wscale); + + return get_cookie_sock(sk, skb, req, &rt->u.dst); +} + +#endif diff -u --recursive --new-file v2.1.43/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.1.43/linux/net/ipv4/sysctl_net_ipv4.c Mon Jun 16 16:36:01 1997 +++ linux/net/ipv4/sysctl_net_ipv4.c Thu Jun 26 12:33:41 1997 @@ -60,8 +60,8 @@ extern int sysctl_tcp_max_delay_acks; extern int sysctl_tcp_fin_timeout; extern int sysctl_tcp_syncookies; -extern int sysctl_tcp_always_syncookie; extern int sysctl_tcp_syn_retries; +extern int sysctl_tcp_stdurg; extern int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp); @@ -203,10 +203,12 @@ {NET_IPV4_IGMP_AGE_THRESHOLD, "igmp_age_threshold", &sysctl_igmp_age_threshold, sizeof(int), 0644, NULL, &proc_dointvec}, #endif +#ifdef CONFIG_SYN_COOKIES {NET_TCP_SYNCOOKIES, "tcp_syncookies", &sysctl_tcp_syncookies, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_TCP_ALWAYS_SYNCOOKIE, "tcp_always_syncookie", - &sysctl_tcp_always_syncookie, sizeof(int), 0644, NULL, &proc_dointvec}, +#endif + {NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg, + sizeof(int), 0644, NULL, &proc_dointvec}, {0} }; diff -u --recursive --new-file v2.1.43/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.43/linux/net/ipv4/tcp_input.c Mon Jun 16 16:36:02 1997 +++ linux/net/ipv4/tcp_input.c Thu Jun 26 12:33:41 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.52 1997/05/31 12:36:42 freitag Exp $ + * Version: $Id: tcp_input.c,v 1.53 1997/06/06 20:38:00 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -65,6 +65,7 @@ int sysctl_tcp_syncookies; int sysctl_tcp_always_syncookie; int sysctl_tcp_max_delay_acks = MAX_DELAY_ACK; +int sysctl_tcp_stdurg; static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj; @@ -288,7 +289,7 @@ * FIXME: surely this can be more efficient. -- erics */ -void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp) +void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, int no_fancy) { unsigned char *ptr; int length=(th->doff*4)-sizeof(struct tcphdr); @@ -323,21 +324,21 @@ break; case TCPOPT_WINDOW: if(opsize==TCPOLEN_WINDOW && th->syn) - if (sysctl_tcp_window_scaling) { + if (!no_fancy && sysctl_tcp_window_scaling) { tp->wscale_ok = 1; tp->snd_wscale = *(__u8 *)ptr; } break; case TCPOPT_SACK_PERM: if(opsize==TCPOLEN_SACK_PERM && th->syn) - if (sysctl_tcp_sack) + if (sysctl_tcp_sack && !no_fancy) tp->sack_ok = 1; case TCPOPT_TIMESTAMP: if(opsize==TCPOLEN_TIMESTAMP) { /* Cheaper to set again then to * test syn. Optimize this? */ - if (sysctl_tcp_timestamps) + if (sysctl_tcp_timestamps && !no_fancy) tp->tstamp_ok = 1; tp->saw_tstamp = 1; tp->rcv_tsval = ntohl(*(__u32 *)ptr); @@ -345,6 +346,8 @@ } break; case TCPOPT_SACK: + if (no_fancy) + break; tp->sacks = (opsize-2)>>3; if (tp->sacks<<3 == opsize-2) { int i; @@ -385,7 +388,7 @@ return 1; } } - tcp_parse_options(th,tp); + tcp_parse_options(th,tp,0); return 1; } @@ -1233,7 +1236,7 @@ * place. We handle URGent data wrong. We have to - as * BSD still doesn't use the correction from RFC961. * For 1003.1g we should support a new option TCP_STDURG to permit - * either form. + * either form (or just set the sysctl tcp_stdurg). */ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) @@ -1241,7 +1244,7 @@ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); u32 ptr = ntohs(th->urg_ptr); - if (ptr) + if (ptr && !sysctl_tcp_stdurg) ptr--; ptr += ntohl(th->seq); @@ -1459,13 +1462,11 @@ /* These use the socket TOS.. * might want to be the received TOS */ - if(th->ack) + if(th->ack) return 1; /* send reset */ if(th->syn) { - __u32 isn = tp->af_specific->init_sequence(sk, skb); - - if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0) + if(tp->af_specific->conn_request(sk, skb, opt, 0) < 0) return 1; /* Now we have several options: In theory there is @@ -1531,7 +1532,7 @@ tp->fin_seq = skb->seq; tcp_set_state(sk, TCP_ESTABLISHED); - tcp_parse_options(th,tp); + tcp_parse_options(th,tp,0); /* FIXME: need to make room for SACK still */ if (tp->wscale_ok == 0) { tp->snd_wscale = tp->rcv_wscale = 0; @@ -1574,7 +1575,7 @@ * tcp_connect. */ tcp_set_state(sk, TCP_SYN_RECV); - tcp_parse_options(th,tp); + tcp_parse_options(th,tp,0); if (tp->saw_tstamp) { tp->ts_recent = tp->rcv_tsval; tp->ts_recent_stamp = jiffies; @@ -1616,6 +1617,8 @@ sk->shutdown = SHUTDOWN_MASK; isn = tp->rcv_nxt + 128000; + if (isn == 0) + isn++; sk = tp->af_specific->get_sock(skb, th); @@ -1710,8 +1713,10 @@ tp->snd_wl1 = skb->seq; tp->snd_wl2 = skb->ack_seq; - } else + } else { + SOCK_DEBUG(sk, "bad ack\n"); return 1; + } break; case TCP_FIN_WAIT1: diff -u --recursive --new-file v2.1.43/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.43/linux/net/ipv4/tcp_ipv4.c Thu May 15 16:48:06 1997 +++ linux/net/ipv4/tcp_ipv4.c Thu Jun 26 12:33:41 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.43 1997/05/06 09:31:44 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.49 1997/06/09 13:27:35 freitag Exp $ * * IPv4 specific functions * @@ -30,6 +30,9 @@ * David S. Miller : Change semantics of established hash, * half is devoted to TIME_WAIT sockets * and the rest go in the other half. + * Andi Kleen : Add support for syncookies and fixed + * some bugs: ip options weren't passed to + * the TCP layer, missed a check for an ACK bit. */ #include @@ -48,6 +51,7 @@ extern int sysctl_tcp_tsack; extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; +extern int sysctl_tcp_syncookies; static void tcp_v4_send_reset(struct sk_buff *skb); @@ -403,7 +407,7 @@ #endif -static __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) +static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) { return secure_tcp_sequence_number(sk->saddr, sk->daddr, skb->h.th->dest, @@ -835,6 +839,8 @@ /* Don't offer more than they did. * This way we don't have to memorize who said what. + * FIXME: maybe this should be changed for better performance + * with syncookies. */ req->mss = min(mss, req->mss); @@ -891,17 +897,13 @@ sizeof(struct ip_options) + req->af.v4_req.opt->optlen); } -static struct or_calltable or_ipv4 = { +struct or_calltable or_ipv4 = { tcp_v4_send_synack, tcp_v4_or_free }; -static int tcp_v4_syn_filter(struct sock *sk, struct sk_buff *skb, __u32 saddr) -{ - return 0; -} - -int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) +int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, + __u32 isn) { struct ip_options *opt = (struct ip_options *) ptr; struct tcp_opt tp; @@ -909,23 +911,39 @@ struct tcphdr *th = skb->h.th; __u32 saddr = skb->nh.iph->saddr; __u32 daddr = skb->nh.iph->daddr; +#ifdef CONFIG_SYN_COOKIES + int want_cookie = 0; +#else +#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */ +#endif /* If the socket is dead, don't accept the connection. */ - if (sk->dead) { - SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk); - tcp_statistics.TcpAttemptFails++; - return -ENOTCONN; - } + if (sk->dead) + goto dead; - if (sk->ack_backlog >= sk->max_ack_backlog || - tcp_v4_syn_filter(sk, skb, saddr)) { - SOCK_DEBUG(sk, "dropping syn ack:%d max:%d\n", sk->ack_backlog, - sk->max_ack_backlog); -#ifdef CONFIG_IP_TCPSF - tcp_v4_random_drop(sk); + if (sk->ack_backlog >= sk->max_ack_backlog) { +#ifdef CONFIG_SYN_COOKIES + if (sysctl_tcp_syncookies) { + static unsigned long warntime; + + if (jiffies - warntime > HZ*60) { + warntime = jiffies; + printk(KERN_INFO + "possible SYN flooding on port %d. Sending cookies.\n", ntohs(skb->h.th->dest)); + } + want_cookie = 1; + } else #endif - tcp_statistics.TcpAttemptFails++; - goto exit; + { + SOCK_DEBUG(sk, "dropping syn ack:%d max:%d\n", sk->ack_backlog, + sk->max_ack_backlog); + tcp_statistics.TcpAttemptFails++; + goto exit; + } + } else { + if (isn == 0) + isn = tcp_v4_init_sequence(sk, skb); + sk->ack_backlog++; } req = tcp_openreq_alloc(); @@ -934,15 +952,12 @@ goto exit; } - sk->ack_backlog++; - req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ req->rcv_isn = skb->seq; - req->snt_isn = isn; - tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; + tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; tp.in_mss = 536; - tcp_parse_options(th,&tp); + tcp_parse_options(th,&tp, want_cookie); if (tp.saw_tstamp) req->ts_recent = tp.rcv_tsval; req->mss = tp.in_mss; @@ -954,8 +969,17 @@ req->af.v4_req.loc_addr = daddr; req->af.v4_req.rmt_addr = saddr; + /* Note that we ignore the isn passed from the TIME_WAIT + * state here. That's the price we pay for cookies. + */ + if (want_cookie) + isn = cookie_v4_init_sequence(sk, skb, &req->mss); + + req->snt_isn = isn; + /* IPv4 options */ req->af.v4_req.opt = NULL; + if (opt && opt->optlen) { int opt_size = sizeof(struct ip_options) + opt->optlen; @@ -973,36 +997,50 @@ tcp_v4_send_synack(sk, req); - req->expires = jiffies + TCP_TIMEOUT_INIT; - tcp_inc_slow_timer(TCP_SLT_SYNACK); - tcp_synq_queue(&sk->tp_pinfo.af_tcp, req); + if (want_cookie) { + if (req->af.v4_req.opt) + kfree(req->af.v4_req.opt); + tcp_openreq_free(req); + } else { + req->expires = jiffies + TCP_TIMEOUT_INIT; + tcp_inc_slow_timer(TCP_SLT_SYNACK); + tcp_synq_queue(&sk->tp_pinfo.af_tcp, req); + } sk->data_ready(sk, 0); exit: kfree_skb(skb, FREE_READ); return 0; + +dead: + SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk); + tcp_statistics.TcpAttemptFails++; + return -ENOTCONN; } struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, - struct open_request *req) + struct open_request *req, + struct dst_entry *dst) { struct tcp_opt *newtp; struct sock *newsk; - struct rtable *rt; int snd_mss; newsk = sk_alloc(GFP_ATOMIC); - if (newsk == NULL) + if (newsk == NULL) { + if (dst) + dst_release(dst); return NULL; + } memcpy(newsk, sk, sizeof(*newsk)); /* Or else we die! -DaveM */ newsk->sklist_next = NULL; - newsk->opt = NULL; - newsk->dst_cache = NULL; + newsk->opt = req->af.v4_req.opt; + skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); skb_queue_head_init(&newsk->out_of_order_queue); @@ -1072,17 +1110,21 @@ newsk->rcv_saddr = req->af.v4_req.loc_addr; /* options / mss / route_cache */ - newsk->opt = req->af.v4_req.opt; - if (ip_route_output(&rt, - newsk->opt && newsk->opt->srr ? newsk->opt->faddr : newsk->daddr, - newsk->saddr, newsk->ip_tos, NULL)) { - kfree(newsk); - return NULL; - } - - newsk->dst_cache = &rt->u.dst; - - snd_mss = rt->u.dst.pmtu; + if (dst == NULL) { + struct rtable *rt; + + if (ip_route_output(&rt, + newsk->opt && newsk->opt->srr ? + newsk->opt->faddr : newsk->daddr, + newsk->saddr, newsk->ip_tos, NULL)) { + kfree(newsk); + return NULL; + } + dst = &rt->u.dst; + } + newsk->dst_cache = dst; + + snd_mss = dst->pmtu; /* FIXME: is mtu really the same as snd_mss? */ newsk->mtu = snd_mss; @@ -1124,7 +1166,7 @@ return newsk; } -struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb) +static inline struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb, struct ip_options *opt) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); struct open_request *req = tp->syn_wait_queue; @@ -1133,8 +1175,13 @@ * as we checked the user count on tcp_rcv and we're * running from a soft interrupt. */ - if(!req) + if(!req) { +#ifdef CONFIG_SYN_COOKIES + goto checkcookie; +#else return sk; +#endif + } while(req) { if (req->af.v4_req.rmt_addr == skb->nh.iph->saddr && @@ -1147,7 +1194,7 @@ * yet accepted()... */ sk = req->sk; - break; + goto ende; } /* Check for syn retransmission */ @@ -1161,20 +1208,28 @@ return NULL; } - sk = tp->af_specific->syn_recv_sock(sk, skb, req); + if (!skb->h.th->ack) + return sk; + + sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL); tcp_dec_slow_timer(TCP_SLT_SYNACK); if (sk == NULL) return NULL; req->expires = 0UL; req->sk = sk; - break; + goto ende; } req = req->dl_next; } - skb_orphan(skb); - skb_set_owner_r(skb, sk); +#ifdef CONFIG_SYN_COOKIES +checkcookie: + sk = cookie_v4_check(sk, skb, opt); +#endif +ende: skb_orphan(skb); + if (sk) + skb_set_owner_r(skb, sk); return sk; } @@ -1195,20 +1250,28 @@ goto ok; } - if (sk->state == TCP_LISTEN) { - struct sock *nsk; + /* + * We check packets with only the SYN bit set against the + * open_request queue too: This increases connection latency a bit, + * but is required to detect retransmitted SYNs. + * + * The ACK/SYN bit check is probably not needed here because + * it is checked later again (we play save now). + */ + if (sk->state == TCP_LISTEN && (skb->h.th->ack || skb->h.th->syn)) { + struct sock *nsk; - /* Find possible connection requests. */ - nsk = tcp_v4_check_req(sk, skb); - if (nsk == NULL) + /* Find possible connection requests. */ + nsk = tcp_v4_check_req(sk, skb, &(IPCB(skb)->opt)); + if (nsk == NULL) goto discard_it; - - release_sock(sk); - lock_sock(nsk); + + release_sock(sk); + lock_sock(nsk); sk = nsk; } - if (tcp_rcv_state_process(sk, skb, skb->h.th, NULL, skb->len) == 0) + if (tcp_rcv_state_process(sk, skb, skb->h.th, &(IPCB(skb)->opt), skb->len) == 0) goto ok; reset: @@ -1352,7 +1415,6 @@ tcp_v4_rebuild_header, tcp_v4_conn_request, tcp_v4_syn_recv_sock, - tcp_v4_init_sequence, tcp_v4_get_sock, ip_setsockopt, ip_getsockopt, diff -u --recursive --new-file v2.1.43/linux/net/ipv4/utils.c linux/net/ipv4/utils.c --- v2.1.43/linux/net/ipv4/utils.c Thu May 15 16:48:06 1997 +++ linux/net/ipv4/utils.c Thu Jun 26 12:33:41 1997 @@ -13,7 +13,7 @@ * Fixes: * Alan Cox : verify_area check. * Alan Cox : removed old debugging. - * + * Andi Kleen : add net_ratelimit() * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -89,3 +89,24 @@ return(htonl(l)); } +/* + * This enforces a rate limit: not more than one kernel message + * every 5secs to make a denial-of-service attack impossible. + * + * All warning printk()s should be guarded by this function. + */ +int net_ratelimit(void) +{ + static unsigned long last_msg; + static int missed; + + if ((jiffies - last_msg) >= 5*HZ) { + if (missed) + printk(KERN_WARNING "ipv4: (%d messages suppressed. Flood?)\n", missed); + missed = 0; + last_msg = jiffies; + return 1; + } + missed++; + return 0; +} diff -u --recursive --new-file v2.1.43/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.1.43/linux/net/ipv6/icmp.c Tue May 13 22:41:24 1997 +++ linux/net/ipv6/icmp.c Thu Jun 26 12:33:41 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.9 1997/04/29 09:38:42 mj Exp $ + * $Id: icmp.c,v 1.10 1997/06/05 11:07:20 schenk Exp $ * * Based on net/ipv4/icmp.c * @@ -405,7 +405,23 @@ case CHECKSUM_HW: if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, skb->csum)) { - printk(KERN_DEBUG "icmpv6 checksum failed\n"); + printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", + ntohs(saddr->in6_u.u6_addr16[0]), + ntohs(saddr->in6_u.u6_addr16[1]), + ntohs(saddr->in6_u.u6_addr16[2]), + ntohs(saddr->in6_u.u6_addr16[3]), + ntohs(saddr->in6_u.u6_addr16[4]), + ntohs(saddr->in6_u.u6_addr16[5]), + ntohs(saddr->in6_u.u6_addr16[6]), + ntohs(saddr->in6_u.u6_addr16[7]), + ntohs(daddr->in6_u.u6_addr16[0]), + ntohs(daddr->in6_u.u6_addr16[1]), + ntohs(daddr->in6_u.u6_addr16[2]), + ntohs(daddr->in6_u.u6_addr16[3]), + ntohs(daddr->in6_u.u6_addr16[4]), + ntohs(daddr->in6_u.u6_addr16[5]), + ntohs(daddr->in6_u.u6_addr16[6]), + ntohs(daddr->in6_u.u6_addr16[7])); goto discard_it; } default: diff -u --recursive --new-file v2.1.43/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.43/linux/net/ipv6/tcp_ipv6.c Mon Jun 16 16:36:02 1997 +++ linux/net/ipv6/tcp_ipv6.c Thu Jun 26 12:33:41 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.32 1997/06/04 08:28:58 davem Exp $ + * $Id: tcp_ipv6.c,v 1.33 1997/06/06 20:38:10 freitag Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -695,7 +695,7 @@ * Can some kind of merge be done? -- erics */ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, - __u32 isn) + __u32 isn) { struct tcp_opt tp; struct open_request *req; @@ -711,6 +711,9 @@ if (skb->protocol == __constant_htons(ETH_P_IP)) return tcp_v4_conn_request(sk, skb, ptr, isn); + if (isn == 0) + isn = tcp_v6_init_sequence(sk,skb); + /* * There are no SYN attacks on IPv6, yet... */ @@ -735,7 +738,7 @@ req->snt_isn = isn; tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; tp.in_mss = 536; - tcp_parse_options(skb->h.th,&tp); + tcp_parse_options(skb->h.th,&tp,0); if (tp.saw_tstamp) req->ts_recent = tp.rcv_tsval; req->mss = tp.in_mss; @@ -778,10 +781,10 @@ } static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, - struct open_request *req) + struct open_request *req, + struct dst_entry *dst) { struct ipv6_pinfo *np; - struct dst_entry *dst; struct flowi fl; struct tcp_opt *newtp; struct sock *newsk; @@ -791,11 +794,11 @@ * v6 mapped */ - newsk = tcp_v4_syn_recv_sock(sk, skb, req); + newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst); - if (newsk == NULL) + if (newsk == NULL) return NULL; - + np = &newsk->net_pinfo.af_inet6; ipv6_addr_set(&np->daddr, 0, 0, __constant_htonl(0x0000FFFF), @@ -813,8 +816,11 @@ } newsk = sk_alloc(GFP_ATOMIC); - if (newsk == NULL) + if (newsk == NULL) { + if (dst) + dst_release(dst); return NULL; + } memcpy(newsk, sk, sizeof(*newsk)); @@ -902,18 +908,20 @@ ipv6_addr_copy(&np->rcv_saddr, &req->af.v6_req.loc_addr); np->oif = req->af.v6_req.dev; - /* - * options / mss / route cache - */ - - fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = &np->saddr; - fl.dev = np->oif; - fl.uli_u.ports.dport = newsk->dummy_th.dest; - fl.uli_u.ports.sport = newsk->dummy_th.source; - - dst = ip6_route_output(newsk, &fl); + if (dst == NULL) { + /* + * options / mss / route cache + */ + + fl.proto = IPPROTO_TCP; + fl.nl_u.ip6_u.daddr = &np->daddr; + fl.nl_u.ip6_u.saddr = &np->saddr; + fl.dev = np->oif; + fl.uli_u.ports.dport = newsk->dummy_th.dest; + fl.uli_u.ports.sport = newsk->dummy_th.source; + + dst = ip6_route_output(newsk, &fl); + } ip6_dst_store(newsk, dst); @@ -1051,7 +1059,7 @@ } skb_orphan(skb); - sk = tp->af_specific->syn_recv_sock(sk, skb, req); + sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL); tcp_dec_slow_timer(TCP_SLT_SYNACK); @@ -1308,7 +1316,6 @@ tcp_v6_rebuild_header, tcp_v6_conn_request, tcp_v6_syn_recv_sock, - tcp_v6_init_sequence, tcp_v6_get_sock, ipv6_setsockopt, ipv6_getsockopt, @@ -1328,7 +1335,6 @@ tcp_v4_rebuild_header, tcp_v6_conn_request, tcp_v6_syn_recv_sock, - tcp_v6_init_sequence, tcp_v6_get_sock, ipv6_setsockopt, ipv6_getsockopt, diff -u --recursive --new-file v2.1.43/linux/net/unix/af_unix.c linux/net/unix/af_unix.c --- v2.1.43/linux/net/unix/af_unix.c Mon Jun 16 16:36:02 1997 +++ linux/net/unix/af_unix.c Thu Jun 26 12:33:41 1997 @@ -450,7 +450,7 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len, int type, unsigned hash, int *error) { - int old_fs; + unsigned long old_fs; int err; struct inode *inode; unix_socket *u; diff -u --recursive --new-file v2.1.43/linux/scripts/ksymoops.cc linux/scripts/ksymoops.cc --- v2.1.43/linux/scripts/ksymoops.cc Sun Nov 10 04:04:07 1996 +++ linux/scripts/ksymoops.cc Thu Jun 26 12:33:41 1997 @@ -31,6 +31,7 @@ // * Only resolves operands of jump and call instructions. #include +#include #include #include #include @@ -184,9 +185,23 @@ char buf[1024]; int lines = 0; + int eip_seen = 0; + long offset; while (fgets(buf, sizeof(buf), objdump_FILE)) { + if (eip_seen && buf[4] == ':') { + // assume objdump from binutils 2.8..., reformat to old style + offset = strtol(buf, 0, 16); + char newbuf[sizeof(buf)]; + memset(newbuf, '\0', sizeof(newbuf)); + ostrstream ost(newbuf, sizeof(newbuf)); + ost.width(8); + ost << offset; + ost << " <_EIP+" << offset << ">: " << &buf[6] << ends; + strcpy(buf, newbuf); + } if (!strnequ(&buf[9], "<_EIP", 5)) continue; + eip_seen = 1; if (strstr(buf, " is out of bounds")) break; lines++; @@ -195,19 +210,28 @@ cout << buf; continue; } - long offset = strtol(buf, 0, 16); - char* bp_0 = strchr(buf, '>') + 2; + offset = strtol(buf, 0, 16); + char* bp_0 = strchr(buf, '>'); KSym* ksym = find(eip_addr + offset); + if (bp_0) + bp_0 += 2; + else + bp_0 = strchr(buf, ':'); if (ksym) cout << *ksym << ' '; - char* bp = bp_0; + char *bp_1 = strstr(bp_0, "\t"); // objdump from binutils 2.8... + if (bp_1) + ++bp_1; + else + bp_1 = bp_0; + char *bp = bp_1; while (!isspace(*bp)) bp++; while (isspace(*bp)) bp++; - if (*bp != '0') { + if (!isxdigit(*bp)) { cout << bp_0; - } else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn + } else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn long rel_addr = strtol(bp, 0, 16); ksym = find(eip_addr + rel_addr); if (ksym) {