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
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.
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
This is the protocol used for computer communication over amateur
<mailto:natalia@nikhefk.nikhef.nl>
'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:
<http://mikonos.dia.unisa.it/tcfs>
'm' all linux/mtio.h conflict!
--- /dev/null
+README for the COPS LocalTalk Linux driver (cops.c).
+ By Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+
+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"
(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
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
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; \
# 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)
.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
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);
}
|
#include <linux/linkage.h>
-
-/*
- * 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 <asm/entry.h>
|################################
| (1) EXAMPLE CALL-OUTS #
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..
#
+# $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
# 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
# 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
archclean:
@$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
+ $(MAKE) -C arch/$(ARCH)/tools clean
archdep:
@$(MAKEBOOT) dep
# 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 <zImage; \
+ else \
+ mcopy -o zImage a:vmlinux; \
+ fi
dep:
$(CPP) -M *.[cS] > .depend
clean:
- rm -f zImage zImage.tmp
+ rm -f zImage zImage.tmp mkboot
dummy:
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/*
+ * 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;
+}
# 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
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
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)'
+if [ "$CONFIG_SGI" != "y" ]; then
+ mainmenu_option next_comment
+ comment 'ISDN subsystem'
-bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
-if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
- source drivers/cdrom/Config.in
+ 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
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+/*
+ * 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... <sigh>
+ */
+
+/*
+ * 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";
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/decstation.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+/*
+ * 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... <sigh>
+ */
+
+/*
+ * 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 <sigh>
+ * 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
--- /dev/null
+/*
+ * 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 <asm/dec/decstation.h>
+#include <asm/dec/maxine.h> /* FIXME: what about other decstations? */
+#include <asm/bootinfo.h>
+
+/*
+ * 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 */
+
--- /dev/null
+/*
+ * 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 <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/mc146818rtc.h>
+#include <asm/vector.h>
+
+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
+};
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/bootinfo.h>
+
+ .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 <sigh>
+ * 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
--- /dev/null
+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)
+ }
+}
--- /dev/null
+/*
+ * linux/arch/mips/dec/process.c
+ *
+ * Reset a DECstation.
+ */
+#include <linux/kernel.h>
+#include <asm/reboot.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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 <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+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;
+}
#
#
-# 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
#
# 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)
#
#
# 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
#
# Kernel hacking
#
+# CONFIG_REMOTE_DEBUG is not set
# CONFIG_PROFILE is not set
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/vector.h>
+
+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
--- /dev/null
+/*
+ * Deskstation rPC44/Tyne specific interrupt handler code
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#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)
--- /dev/null
+/*
+ * 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 <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/sni.h>
+
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * linux/arch/mips/deskstation/process.c
+ *
+ * Reset a Deskstation.
+ */
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+/*
+ * 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");
+}
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/types.h>
+
+#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; i<MAX_NR_CONSOLES; i++)
+ if (vc_cons_allocated(i)) {
+ int j, k ;
+ for (j=k=0; j<16; j++) {
+ vc_cons[i].d->vc_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)
+{
+}
--- /dev/null
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,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
--- /dev/null
+/*
+ * 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 <linux/delay.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/addrspace.h>
+#include <asm/vector.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+#include <asm/mc146818rtc.h>
+
+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
+};
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+#include <asm/jazz.h>
+
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/dma.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+
+/*
+ * 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<VDMA_PGTBL_ENTRIES; i++)
+ {
+ pgtbl[i].frame = paddr;
+ pgtbl[i].owner = VDMA_PAGE_EMPTY;
+ paddr += VDMA_PAGESIZE;
+ }
+}
+
+/*
+ * 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;
+ flush_cache_all();
+
+ /*
+ * Clear the R4030 translation table
+ */
+ vdma_pgtbl_init();
+
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+ printk("VDMA: R4030 DMA pagetables initialized.\n");
+
+ return KSEG0ADDR(vdma_pagetable_end);
+}
+
+/*
+ * Allocate DMA pagetables using a simple first-fit algorithm
+ */
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
+{
+ VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+ int first;
+ int last;
+ int pages;
+ unsigned int frame;
+ unsigned long laddr;
+ int i;
+
+ /* check arguments */
+
+ if (paddr > 0x1fffffff)
+ {
+ if (vdma_debug)
+ printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
+ return VDMA_ERROR; /* invalid physical address */
+ }
+ if (size > 0x400000 || size == 0)
+ {
+ if (vdma_debug)
+ printk("vdma_alloc: Invalid size: %08lx\n",size);
+ return VDMA_ERROR; /* invalid physical address */
+ }
+
+ /*
+ * Find free chunk
+ */
+ pages = (size + 4095) >> 12; /* no. of pages to allocate */
+ first = 0;
+ while (1)
+ {
+ while (entry[first].owner != VDMA_PAGE_EMPTY &&
+ first < VDMA_PGTBL_ENTRIES)
+ first++;
+ if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
+ return VDMA_ERROR;
+
+ last = first+1;
+ while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
+ last++;
+
+ if (last-first == pages)
+ break; /* found */
+ }
+
+ /*
+ * Mark pages as allocated
+ */
+ laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
+ frame = paddr & ~(VDMA_PAGESIZE-1);
+
+ for (i=first; i<last; i++)
+ {
+ entry[i].frame = frame;
+ entry[i].owner = laddr;
+ frame += VDMA_PAGESIZE;
+ }
+
+ /*
+ * Update translation table and return logical start address
+ */
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+ if (vdma_debug > 1)
+ printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
+ pages,laddr);
+
+ if (vdma_debug > 2)
+ {
+ printk("LADDR: ");
+ for (i=first; i<last; i++)
+ printk("%08x ",i<<12);
+ printk("\nPADDR: ");
+ for (i=first; i<last; i++)
+ printk("%08x ",entry[i].frame);
+ printk("\nOWNER: ");
+ for (i=first; i<last; i++)
+ printk("%08x ",entry[i].owner);
+ printk("\n");
+ }
+
+ return laddr;
+}
+
+/*
+ * Free previously allocated dma translation pages
+ * Note that this does NOT change the translation table,
+ * it just marks the free'd pages as unused!
+ */
+int vdma_free(unsigned long laddr)
+{
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+ int i;
+
+ i = laddr >> 12;
+
+ if (pgtbl[i].owner != laddr)
+ {
+ printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
+ laddr);
+ return -1;
+ }
+
+ while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
+ {
+ pgtbl[i].owner = VDMA_PAGE_EMPTY;
+ i++;
+ }
+
+ if (vdma_debug > 1)
+ printk("vdma_free: freed %ld pages starting from %08lx\n",
+ i-(laddr>>12),laddr);
+
+ return 0;
+}
+
+/*
+ * Map certain page(s) to another physical address.
+ * Caller must have allocated the page(s) before.
+ */
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
+{
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+ int first, 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<first+pages; i++)
+ printk("%08x ",i<<12);
+ printk("\nPADDR: ");
+ for (i=first; i<first+pages; i++)
+ printk("%08x ",pgtbl[i].frame);
+ printk("\nOWNER: ");
+ for (i=first; i<first+pages; i++)
+ printk("%08x ",pgtbl[i].owner);
+ printk("\n");
+ }
+
+ return 0;
+}
+
+/*
+ * Translate a physical address to a logical address.
+ * This will return the logical address of the first
+ * match.
+ */
+unsigned long vdma_phys2log(unsigned long paddr)
+{
+ int i;
+ int frame;
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+ frame = paddr & ~(VDMA_PAGESIZE-1);
+
+ for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+ {
+ if (pgtbl[i].frame == frame)
+ break;
+ }
+
+ if (i == VDMA_PGTBL_ENTRIES)
+ return ~0UL;
+
+ return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
+}
+
+/*
+ * Translate a logical DMA address to a physical address
+ */
+unsigned long vdma_log2phys(unsigned long laddr)
+{
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+ return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
+}
+
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * linux/arch/mips/jazz/process.c
+ *
+ * Reset a Jazz machine.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+
+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 */
+}
--- /dev/null
+/*
+ * 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 <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/jazz.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+#include <asm/io.h>
+
+/*
+ * 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;
+}
# 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
#
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:
+++ /dev/null
-/*
- * bios 32 replacement
- */
-unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
-{
- return memory_start;
-}
--- /dev/null
+/*
+ * 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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/branch.h>
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * 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;
+}
* 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/<cputype>.S
+ * code is in arch/mips/<ISA-level>/<cputype>.S
*/
+#include <linux/config.h>
#include <linux/sys.h>
#include <asm/asm.h>
+#include <asm/current.h>
#include <asm/errno.h>
-#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/stackframe.h>
#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
#include <asm/unistd.h>
-/*
- * 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
.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
+ .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
- .rdata
- .align PTRLOG
-dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
+ 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.
.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"
#include <linux/sys.h>
#include <asm/asm.h>
-#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
+#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/gdb-stub.h>
*/
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)
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)
* 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)
*/
move a0,sp
+
jal handle_exception
- nop
+ nop
/*
* restore all writable registers, in reverse order
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)
* 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
lw $1,GDB_FR_REG1(sp)
lw sp,GDB_FR_REG29(sp) /* Deallocate stack */
- ERET
+ eret
.set at
.set reorder
END(trap_low)
#include <asm/asm.h>
#include <asm/mipsregs.h>
-#include <asm/segment.h>
#include <asm/cachectl.h>
#include <asm/system.h>
#include <asm/gdb-stub.h>
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);
* 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();
}
* NB: We flush both caches, just to be sure...
*/
- sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE);
+ flush_cache_all();
return;
/* NOTREACHED */
break;
/*
* 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 <linux/config.h>
#include <linux/tasks.h>
#include <asm/asm.h>
-#include <asm/segment.h>
+#include <asm/current.h>
+#include <asm/offset.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
#include <asm/cachectl.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/stackframe.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+
+ .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
-#define PAGE_SIZE 0x1000
+ /* 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
- .text
- .set mips3
/*
- * This is space for the interrupt handlers.
- * They are located at virtual address KSEG[01] (physical 0x0)
+ * Kernel entry point
*/
- /*
- * 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
-
-/******************************************************************************/
+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)
+
+ jal prom_init /* prom_init(argc, argv, envp); */
+ nop
+#endif
+ /* 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)
/*
- * Kernel entry
+ * wire_mappings - used to map hardware registers, r4xx0 version.
*/
- .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
-#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)
+LEAF(wire_mappings_r4xx0)
+ mtc0 zero, CP0_WIRED
+ nop
+ nop
+ nop
+ j ra
+ nop
+ END(wire_mappings_r4xx0)
/*
- * wire_mappings - used to map hardware registers
+ * R3000 version of wire_mappings.
*/
- 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)
-
- .data
+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
/*
* Build an entry for table of wired entries
*/
* 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.
*/
/*
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.
* 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
--- /dev/null
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/pgtable.h>
+
+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 };
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
* 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 <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/msg.h>
#include <linux/shm.h>
-#include <asm/segment.h>
+#include <asm/ipc.h>
+#include <asm/uaccess.h>
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
- * This is really horribly ugly; removing this will need some minor
- * changes in libc.
+ * 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();
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;
}
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;
}
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())
out:
unlock_kernel();
return ret;
-#else /* CONFIG_SYSVIPC */
- return -ENOSYS;
-#endif /* CONFIG_SYSVIPC */
}
--- /dev/null
+/* $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!!!! */
--- /dev/null
+/*
+ * 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 <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/shm.h>
+#include <linux/personality.h>
+#include <linux/elfcore.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include <linux/config.h>
+
+#define DLINFO_ITEMS 12
+
+#include <linux/elf.h>
+
+#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; i<interp_elf_ex->e_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; i<elf_ex.e_phnum; i++)
+ if((elf_phdata + i)->p_type == PT_LOAD) j++;
+
+ if(j != 1) {
+ kfree(elf_phdata);
+ return -ENOEXEC;
+ }
+
+ while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+
+ /* Now use mmap to map the library into memory. */
+ error = do_mmap(file,
+ elf_phdata->p_vaddr & 0xfffff000,
+ elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE | 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 <jeremy@sw.oz.au>
+ */
+
+/* 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
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/tty.h>
+
+#include <asm/uaccess.h>
+#include <asm/ioctl.h>
+#include <asm/ioctls.h>
+
+#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;
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
+
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#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("<f[%d] hndlr[%08lx] msk[%08lx]>", 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;
+}
* 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 <linux/ptrace.h>
+#include <linux/config.h>
#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/timex.h>
#include <linux/malloc.h>
#include <linux/random.h>
#include <asm/jazz.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
-
-#define TIMER_IRQ 0 /* Keep this in sync with time.c */
+#include <asm/vector.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#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();
- cache_A1 &= mask;
- outb(cache_A1,0xA1);
+ mask_irq(irq_nr);
+ restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ unmask_irq(irq_nr);
restore_flags(flags);
}
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)
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) ? '+' : ' ',
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
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);
}
/*
*/
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 *),
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;
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<<irq);
- outb(cache_21,0x21);
- } else {
- cache_21 &= ~(1<<2);
- cache_A1 &= ~(1<<(irq-8));
- outb(cache_21,0x21);
- outb(cache_A1,0xA1);
- }
- }
- restore_flags(flags);
- return 0;
-}
+ retval = setup_x86_irq(irq, action);
+ if (retval)
+ kfree(action);
+ return retval;
+}
+
void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = *(irq + irq_action);
- struct irqaction * tmp = NULL;
+ struct irqaction * action, **p;
unsigned long flags;
- if (irq > 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)
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
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();
}
+++ /dev/null
-/*
- * Jazz specific C parts
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-
-#include <asm/cachectl.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <asm/segment.h>
-
-unsigned char jazz_fd_inb(unsigned int port)
-{
- unsigned char c;
-
- c = *(volatile unsigned char *) port;
- udelay(1);
-
- return c;
-}
-
-void jazz_fd_outb(unsigned char value, unsigned int port)
-{
- *(volatile unsigned char *) port = value;
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void jazz_fd_enable_dma(void)
-{
- vdma_enable(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_disable_dma(void)
-{
- vdma_disable(JAZZ_FLOPPY_DMA);
-}
-
-int jazz_fd_request_dma(void)
-{
- return 0;
-}
-
-void jazz_fd_free_dma(void)
-{
-}
-
-void jazz_fd_clear_dma_ff(void)
-{
-}
-
-void jazz_fd_set_dma_mode(char mode)
-{
- vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
-}
-
-void jazz_fd_set_dma_addr(unsigned int a)
-{
- vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
-}
-
-void jazz_fd_set_dma_count(unsigned int count)
-{
- vdma_set_count(JAZZ_FLOPPY_DMA, count);
-}
-
-int jazz_fd_get_dma_residue(void)
-{
- return vdma_get_residue(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_enable_irq(void)
-{
-}
-
-void jazz_fd_disable_irq(void)
-{
-}
-
-void jazz_fd_cacheflush(unsigned char *addr, unsigned int size)
-{
- sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-unsigned char jazz_rtc_read_data(void)
-{
- return *(char *)JAZZ_RTC_BASE;
-}
-
-void jazz_rtc_write_data(unsigned char data)
-{
- *(char *)JAZZ_RTC_BASE = data;
-}
+++ /dev/null
-/*
- * 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 <linux/kernel.h>
-#include <linux/errno.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-#include <asm/jazz.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/dma.h>
-#include <asm/jazzdma.h>
-
-
-static unsigned long vdma_pagetable_start = 0;
-static unsigned long vdma_pagetable_end = 0;
-
-/*
- * Debug stuff
- */
-#define vdma_debug ((CONF_DEBUG_VDMA) ? debuglvl : 0)
-
-static int debuglvl = 3;
-
-/*
- * Local prototypes
- */
-static void vdma_pgtbl_init(void);
-
-/*
- * Initialize the Jazz R4030 dma controller
- */
-unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
-{
- /*
- * Allocate 32k of memory for DMA page tables.
- * This needs to be page aligned and should be
- * uncached to avoid cache flushing after every
- * update.
- */
- vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
- vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
-
- /*
- * Clear the R4030 translation table
- */
- vdma_pgtbl_init();
-
- r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
- r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
- r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
- printk("VDMA: R4030 DMA pagetables initialized.\n");
- return KSEG0ADDR(vdma_pagetable_end);
-}
-
-/*
- * Allocate DMA pagetables using a simple first-fit algorithm
- */
-unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
-{
- VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
- int first;
- int last;
- int pages;
- unsigned int frame;
- unsigned long laddr;
- int i;
-
- /* check arguments */
-
- if (paddr > 0x1fffffff)
- {
- if (vdma_debug)
- printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
- return VDMA_ERROR; /* invalid physical address */
- }
- if (size > 0x400000 || size == 0)
- {
- if (vdma_debug)
- printk("vdma_alloc: Invalid size: %08lx\n",size);
- return VDMA_ERROR; /* invalid physical address */
- }
-
- /* find free chunk */
- pages = (size + 4095) >> 12; /* no. of pages to allocate */
- first = 0;
- while (1)
- {
- while (entry[first].owner != VDMA_PAGE_EMPTY &&
- first < VDMA_PGTBL_ENTRIES)
- first++;
- if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
- return VDMA_ERROR;
-
- last = first+1;
- while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
- last++;
-
- if (last-first == pages)
- break; /* found */
- }
-
- /* mark pages as allocated */
-
- laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
- frame = paddr & ~(VDMA_PAGESIZE-1);
-
- for (i=first; i<last; i++)
- {
- entry[i].frame = frame;
- entry[i].owner = laddr;
- frame += VDMA_PAGESIZE;
- }
-
- /*
- * update translation table and
- * return logical start address
- */
- r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
- if (vdma_debug > 1)
- printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
- pages,laddr);
-
- if (vdma_debug > 2)
- {
- printk("LADDR: ");
- for (i=first; i<last; i++)
- printk("%08x ",i<<12);
- printk("\nPADDR: ");
- for (i=first; i<last; i++)
- printk("%08x ",entry[i].frame);
- printk("\nOWNER: ");
- for (i=first; i<last; i++)
- printk("%08x ",entry[i].owner);
- printk("\n");
- }
-
- return laddr;
-}
-
-/*
- * Free previously allocated dma translation pages
- * Note that this does NOT change the translation table,
- * it just marks the free'd pages as unused!
- */
-int vdma_free(unsigned long laddr)
-{
- VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
- int i;
-
- i = laddr >> 12;
-
- if (pgtbl[i].owner != laddr)
- {
- printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
- laddr);
- return -1;
- }
-
- while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
- {
- pgtbl[i].owner = VDMA_PAGE_EMPTY;
- i++;
- }
-
- if (vdma_debug > 1)
- printk("vdma_free: freed %ld pages starting from %08lx\n",
- i-(laddr>>12),laddr);
-
- return 0;
-}
-
-/*
- * Map certain page(s) to another physical address.
- * Caller must have allocated the page(s) before.
- */
-int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
-{
- VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
- int first;
- int pages;
-
- if (laddr > 0xffffff)
- {
- if (vdma_debug)
- printk("vdma_map: Invalid logical address: %08lx\n",laddr);
- return -EINVAL; /* invalid logical address */
- }
- if (paddr > 0x1fffffff)
- {
- if (vdma_debug)
- printk("vdma_map: Invalid physical address: %08lx\n",paddr);
- return -EINVAL; /* invalid physical address */
- }
-
- pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
- first = laddr >> 12;
- if (vdma_debug)
- printk("vdma_remap: first=%x, pages=%x\n",first,pages);
- if (first+pages > VDMA_PGTBL_ENTRIES)
- {
- if (vdma_debug)
- printk("vdma_alloc: Invalid size: %08lx\n",size);
- return -EINVAL;
- }
-
- paddr &= ~(VDMA_PAGESIZE-1);
- while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
- {
- if (pgtbl[first].owner != laddr)
- {
- if (vdma_debug)
- printk("Trying to remap other's pages.\n");
- return -EPERM; /* not owner */
- }
- pgtbl[first].frame = paddr;
- paddr += VDMA_PAGESIZE;
- first++;
- pages--;
- }
-
- /* update translation table */
-
- r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
- if (vdma_debug > 2)
- {
- int i;
- pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
- first = laddr >> 12;
- printk("LADDR: ");
- for (i=first; i<first+pages; i++)
- printk("%08x ",i<<12);
- printk("\nPADDR: ");
- for (i=first; i<first+pages; i++)
- printk("%08x ",pgtbl[i].frame);
- printk("\nOWNER: ");
- for (i=first; i<first+pages; i++)
- printk("%08x ",pgtbl[i].owner);
- printk("\n");
- }
-
- return 0;
-}
-
-/*
- * Translate a physical address to a logical address.
- * This will return the logical address of the first
- * match.
- */
-unsigned long vdma_phys2log(unsigned long paddr)
-{
- int i;
- int frame;
- VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
- frame = paddr & ~(VDMA_PAGESIZE-1);
-
- for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
- {
- if (pgtbl[i].frame == frame)
- break;
- }
-
- if (i == VDMA_PGTBL_ENTRIES)
- return 0xffffffff;
-
- return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
-}
-
-/*
- * Translate a logical DMA address to a physical address
- */
-unsigned long vdma_log2phys(unsigned long laddr)
-{
- VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
- return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
-}
-
-/*
- * Initialize the pagetable with a one-to-one mapping of
- * the first 16 Mbytes of main memory and declare all
- * entries to be unused. Using this method will at least
- * allow some early device driver operations to work.
- */
-static void vdma_pgtbl_init(void)
-{
- int i;
- unsigned long paddr = 0;
- VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
- for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
- {
- pgtbl[i].frame = paddr;
- pgtbl[i].owner = VDMA_PAGE_EMPTY;
- paddr += VDMA_PAGESIZE;
- }
-
-/* vdma_stats(); */
-}
-
-/*
- * Print DMA statistics
- */
-void vdma_stats(void)
-{
- int i;
-
- printk("vdma_stats: CONFIG: %08x\n",
- r4030_read_reg32(JAZZ_R4030_CONFIG));
- printk("R4030 translation table base: %08x\n",
- r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
- printk("R4030 translation table limit: %08x\n",
- r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
- printk("vdma_stats: INV_ADDR: %08x\n",
- r4030_read_reg32(JAZZ_R4030_INV_ADDR));
- printk("vdma_stats: R_FAIL_ADDR: %08x\n",
- r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
- printk("vdma_stats: M_FAIL_ADDR: %08x\n",
- r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
- printk("vdma_stats: IRQ_SOURCE: %08x\n",
- r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
- printk("vdma_stats: I386_ERROR: %08x\n",
- r4030_read_reg32(JAZZ_R4030_I386_ERROR));
- printk("vdma_chnl_modes: ");
- for (i=0; i<8; i++)
- printk("%04x ",
- (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
- printk("\n");
- printk("vdma_chnl_enables: ");
- for (i=0; i<8; i++)
- printk("%04x ",
- (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
- printk("\n");
-}
-
-/*
- * DMA transfer functions
- */
-
-/*
- * Enable a DMA channel. Also clear any error conditions.
- */
-void vdma_enable(int channel)
-{
- int status;
-
- if (vdma_debug)
- printk("vdma_enable: channel %d\n",channel);
-
- /*
- * Check error conditions first
- */
- status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
- if (status & 0x400)
- printk("VDMA: Channel %d: Address error!\n",channel);
- if (status & 0x200)
- printk("VDMA: Channel %d: Memory error!\n",channel);
-
- /*
- * Clear all interrupt flags
- */
- r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
- R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
-
- /*
- * Enable the desired channel
- */
- r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
- r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
- R4030_CHNL_ENABLE);
-}
-
-/*
- * Disable a DMA channel
- */
-void vdma_disable(int channel)
-{
- if (vdma_debug)
- {
- int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
-
- printk("vdma_disable: channel %d\n",channel);
- printk("VDMA: channel %d status: %04x (%s) mode: "
- "%02x addr: %06x count: %06x\n",
- channel,status,((status & 0x600) ? "ERROR" : "OK"),
- (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
- (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
- (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
- }
-
- r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
- r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
- ~R4030_CHNL_ENABLE);
-
- /*
- * After disabling a DMA channel a remote bus register should be
- * read to ensure that the current DMA acknowledge cycle is completed.
- */
- *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
-}
-
-/*
- * Set DMA mode. This function accepts the mode values used
- * to set a PC-style DMA controller. For the SCSI and FDC
- * channels, we also set the default modes each time we're
- * called.
- * NOTE: The FAST and BURST dma modes are supported by the
- * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
- * for now.
- */
-void vdma_set_mode(int channel, int mode)
-{
- if (vdma_debug)
- printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
-
- switch(channel)
- {
- case JAZZ_SCSI_DMA: /* scsi */
- r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/* R4030_MODE_FAST | */
-/* R4030_MODE_BURST | */
- R4030_MODE_INTR_EN |
- R4030_MODE_WIDTH_16 |
- R4030_MODE_ATIME_80);
- break;
-
- case JAZZ_FLOPPY_DMA: /* floppy */
- r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/* R4030_MODE_FAST | */
-/* R4030_MODE_BURST | */
- R4030_MODE_INTR_EN |
- R4030_MODE_WIDTH_8 |
- R4030_MODE_ATIME_120);
- break;
-
- case JAZZ_AUDIOL_DMA:
- case JAZZ_AUDIOR_DMA:
- printk("VDMA: Audio DMA not supported yet.\n");
- break;
-
- default:
- printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
- channel);
- }
-
- switch(mode)
- {
- case DMA_MODE_READ:
- r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
- r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
- ~R4030_CHNL_WRITE);
- break;
-
- case DMA_MODE_WRITE:
- r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
- r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
- R4030_CHNL_WRITE);
- break;
-
- default:
- printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
- }
-}
-
-/*
- * Set Transfer Address
- */
-void vdma_set_addr(int channel, long addr)
-{
- if (vdma_debug)
- printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
-
- r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
-}
-
-/*
- * Set Transfer Count
- */
-void vdma_set_count(int channel, int count)
-{
- if (vdma_debug)
- printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
-
- r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
-}
-
-/*
- * Get Residual
- */
-int vdma_get_residue(int channel)
-{
- int residual;
-
- residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
-
- if (vdma_debug)
- printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
-
- return residual;
-}
+++ /dev/null
-/*
- * arch/mips/kernel/magnum4000.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/stackframe.h>
-
-/*
- * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000
- */
- .set noreorder
-
- NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
-
- /*
- * Get pending interrupts
- */
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
- andi t0,0xff00 # isolate pending bits
- beqz t0,spurious_interrupt
- sll t0,16 # delay slot
-
- /*
- * Find irq with highest priority
- * FIXME: This is slow
- */
- la t1,ll_vectors
-1: bltz t0,2f # found pending irq
- sll t0,1
- b 1b
- subu t1,PTRSIZE # delay slot
-
- /*
- * Do the low-level stuff
- */
-2: lw t0,(t1)
- jr t0
- nop # delay slot
- END(mips_magnum_4000_handle_int)
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- */
-ll_sw0: li s1,~IE_SW0
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PRINT("sw0 received...\n")
- li t1,1
- b call_real
- li t3,PTRSIZE # delay slot, re-map to irq level 1
-
-ll_sw1: li s1,~IE_SW1
- PANIC("Unimplemented sw1 handler")
-
-ll_local_dma: li s1,~IE_IRQ0
- PANIC("Unimplemented local_dma handler")
-
-ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
-#if __mips == 3
- dsll t0,1
- ld t0,local_vector(t0)
-#else /* 32 bit */
- lw t0,local_vector(t0)
-#endif
- jr t0
- nop
-
-
-loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
-loc_sound: PANIC("Unimplemented loc_sound handler")
-loc_video: PANIC("Unimplemented loc_video handler")
-loc_scsi: PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
- li t1,JAZZ_KEYBOARD_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_KEYBOARD_IRQ # delay slot
-
-/*
- * Ethernet interrupt handler, remapped to level 2
- */
-loc_ethernet: /* PRINT ("ethernet IRQ\n"); */
- li s1,~JAZZ_IE_ETHERNET
- li t1,JAZZ_ETHERNET_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_ETHERNET_IRQ # delay slot
-
-
-loc_mouse: PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1: li s1,~JAZZ_IE_SERIAL1
- li t1,JAZZ_SERIAL1_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_SERIAL1_IRQ # delay slot
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2: li s1,~JAZZ_IE_SERIAL2
- li t1,JAZZ_SERIAL2_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_SERIAL2_IRQ # delay slot
-
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel: li s1,~JAZZ_IE_PARALLEL
- li t1,JAZZ_PARALLEL_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_PARALLEL_IRQ # delay slot
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy: li s1,~JAZZ_IE_FLOPPY
- li t1,JAZZ_FLOPPY_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_FLOPPY_IRQ # delay slot
-
-/*
- * Now call the real handler
- */
-loc_call: lui s3,%hi(intr_count)
- lw t2,%lo(intr_count)(s3)
- la t0,IRQ_vectors # delay slot
- addiu t2,1
- sw t2,%lo(intr_count)(s3)
-
- /*
- * Temporarily disable interrupt source
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- addu t0,t3 # make ptr to IRQ handler
- lw t0,(t0)
- and t2,s1 # delay slot
- sh t2,JAZZ_IO_IRQ_ENABLE
- jalr t0 # call IRQ handler
- nor s1,zero,s1 # delay slot
-
- /*
- * Reenable interrupt
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- lw t1,%lo(intr_count)(s3) # delay slot
- or t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- subu t1,1
- jr v0
- sw t1,%lo(intr_count)(s3)
-
-ll_eisa_irq: li s1,~IE_IRQ2
- PANIC("Unimplemented eisa_irq handler")
-
-ll_eisa_nmi: li s1,~IE_IRQ3
- PANIC("Unimplemented eisa_nmi handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to a IBM compatible
- */
-ll_timer: lw t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
- li s1,~IE_IRQ4
- li t1,0
- b call_real
- li t3,0 # delay slot, re-map to irq level 0
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count: j return
- mtc0 zero,CP0_COMPARE
-
-/*
- * Now call the real handler
- */
-call_real: lui s3,%hi(intr_count)
- lw t2,%lo(intr_count)(s3)
- la t0,IRQ_vectors # delay slot
- addiu t2,1
- sw t2,%lo(intr_count)(s3)
-
- /*
- * temporarily disable interrupt
- */
- mfc0 t2,CP0_STATUS
- and t2,s1
-
- addu t0,t3
- lw t0,(t0)
- mtc0 t2,CP0_STATUS # delay slot
- jalr t0
- nor s1,zero,s1 # delay slot
-
- /*
- * reenable interrupt
- */
- mfc0 t2,CP0_STATUS
- or t2,s1
- mtc0 t2,CP0_STATUS
-
- lw t2,%lo(intr_count)(s3)
- subu t2,1
-
- jr v0
- sw t2,%lo(intr_count)(s3)
-
-/*
- * Just for debugging...
- */
- LEAF(drawline)
- li t1,0xffffffff
- li t2,0x100
-1: sw t1,(a0)
- addiu a0,a0,4
- addiu t2,t2,-1
- bnez t2,1b
- nop
- jr ra
- nop
- END(drawline)
-
-
- .data
- PTR ll_sw0 # SW0
- PTR ll_sw1 # SW1
- PTR ll_local_dma # Local DMA
- PTR ll_local_dev # Local devices
- PTR ll_eisa_irq # EISA IRQ
- PTR ll_eisa_nmi # EISA NMI
- PTR ll_timer # Timer
-ll_vectors: PTR ll_count # Count/Compare IRQ
-
-local_vector: PTR loc_no_irq
- PTR loc_parallel
- PTR loc_floppy
- PTR loc_sound
- PTR loc_video
- PTR loc_ethernet
- PTR loc_scsi
- PTR loc_keyboard
- PTR loc_mouse
- PTR loc_serial1
- PTR loc_serial2
-
- .align 5
-LEAF(spurious_interrupt)
- /*
- * Nothing happened... (whistle)
- */
- lui t1,%hi(spurious_count)
- lw t0,%lo(spurious_count)(t1)
- la v0,return
- addiu t0,1
- jr ra
- sw t0,%lo(spurious_count)(t1)
- END(spurious_interrupt)
-
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <asm/floppy.h>
+#include <asm/io.h>
+#include <asm/softirq.h>
+
+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);
--- /dev/null
+/*
+ * 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 <linux/bios32.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+
+#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) */
+++ /dev/null
-/*
- * arch/mips/kernel/pica.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- *
- * Acer PICA 61 specific stuff
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/pica.h>
-#include <asm/stackframe.h>
-
-/*
- * acer_pica_61_handle_int: Interrupt handler for the ACER Pica-61 boards
- * FIXME: this is *very* experimental!
- */
- .set noreorder
-
- NESTED(acer_pica_61_handle_int, FR_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
-
- /*
- * Get pending interrupts
- */
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
- andi t0,0xff00 # isolate pending bits
- beqz t0,spurious_interrupt
- sll t0,16 # delay slot
-
- /*
- * Find irq with highest priority
- * FIXME: This is slow - use binary search
- */
- la t1,ll_vectors
-1: bltz t0,2f # found pending irq
- sll t0,1
- b 1b
- subu t1,PTRSIZE # delay slot
-
- /*
- * Do the low-level stuff
- */
-2: lw t0,(t1)
- jr t0
- nop # delay slot
- END(acer_pica_61_handle_int)
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- */
-ll_sw0: li s1,~IE_SW0
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PRINT("sw0 received...\n")
- li t1,1
- b call_real
- li t3,PTRSIZE # delay slot, re-map to irq level 1
-
-ll_sw1: li s1,~IE_SW1
- PANIC("Unimplemented sw1 handler")
-
-ll_local_dma: li s1,~IE_IRQ0
- PANIC("Unimplemented local_dma handler")
-
-ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
-#if __mips == 3
- dsll t0,1
- ld t0,local_vector(t0)
-#else /* 32 bit */
- lw t0,local_vector(t0)
-#endif
- jr t0
- nop
-
-
-loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel: li s1,~JAZZ_IE_PARALLEL
- li t1,JAZZ_PARALLEL_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_PARALLEL_IRQ # delay slot
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy: li s1,~JAZZ_IE_FLOPPY
- li t1,JAZZ_FLOPPY_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_FLOPPY_IRQ # delay slot
-
-/*
- * Now call the real handler
- */
-loc_call: lui s3,%hi(intr_count)
- lw t2,%lo(intr_count)(s3)
- la t0,IRQ_vectors # delay slot
- addiu t2,1
- sw t2,%lo(intr_count)(s3)
-
- /*
- * Temporarily disable interrupt source
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- addu t0,t3 # make ptr to IRQ handler
- lw t0,(t0)
- and t2,s1 # delay slot
- sh t2,JAZZ_IO_IRQ_ENABLE
- jalr t0 # call IRQ handler
- nor s1,zero,s1 # delay slot
-
- /*
- * Reenable interrupt
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- lw t1,%lo(intr_count)(s3) # delay slot
- or t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- subu t1,1
- jr v0
- sw t1,%lo(intr_count)(s3) # delay slot
-
-ll_isa_irq: li s1,~IE_IRQ2
- PANIC("Unimplemented isa_irq handler")
-
-ll_isa_nmi: li s1,~IE_IRQ3
- PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to an IBM compatible
- */
-ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
- li s1,~IE_IRQ4
- li t1,0
- b call_real
- li t3,0 # delay slot, re-map to irq level 0
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count: j return
- mtc0 zero,CP0_COMPARE
-
-/*
- * Now call the real handler
- */
-call_real: lui s3,%hi(intr_count)
- lw t2,%lo(intr_count)(s3)
- la t0,IRQ_vectors
- addiu t2,1
- sw t2,%lo(intr_count)(s3)
-
- /*
- * temporarily disable interrupt
- */
- mfc0 t2,CP0_STATUS
- and t2,s1
-
- addu t0,t3
- lw t0,(t0)
- mtc0 t2,CP0_STATUS # delay slot
- jalr t0
- nor s1,zero,s1 # delay slot
-
- /*
- * reenable interrupt
- */
- mfc0 t2,CP0_STATUS
- or t2,s1
- mtc0 t2,CP0_STATUS
-
- lw t2,%lo(intr_count)(s3)
- subu t2,1
-
- jr v0
- sw t2,%lo(intr_count)(s3)
-
- .data
- PTR ll_sw0 # SW0
- PTR ll_sw1 # SW1
- PTR ll_local_dma # Local DMA
- PTR ll_local_dev # Local devices
- PTR ll_isa_irq # ISA IRQ
- PTR ll_isa_nmi # ISA NMI
- PTR ll_timer # Timer
-ll_vectors: PTR ll_count # Count/Compare IRQ
-
-
-/*
- * Sound? What sound hardware (whistle) ???
- */
-loc_sound: PANIC("Unimplemented loc_sound handler")
-loc_video: PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler, remapped to level 2
- */
-loc_ethernet: li s1,~JAZZ_IE_ETHERNET
- li t1,JAZZ_ETHERNET_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_ETHERNET_IRQ # delay slot
-
-loc_scsi: PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
- li t1,JAZZ_KEYBOARD_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_KEYBOARD_IRQ # re-map to irq level 1
-
-loc_mouse: PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1: li s1,~JAZZ_IE_SERIAL1
- li t1,JAZZ_SERIAL1_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_SERIAL1_IRQ # delay slot
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2: li s1,~JAZZ_IE_SERIAL2
- li t1,JAZZ_SERIAL2_IRQ
- b loc_call
- li t3,PTRSIZE*JAZZ_SERIAL2_IRQ # delay slot
-
- .data
-local_vector: PTR loc_no_irq
- PTR loc_parallel
- PTR loc_floppy
- PTR loc_sound
- PTR loc_video
- PTR loc_ethernet
- PTR loc_scsi
- PTR loc_keyboard
- PTR loc_mouse
- PTR loc_serial1
- PTR loc_serial2
-
- .align 5
- .text
-LEAF(spurious_interrupt)
- /*
- * Nothing happened... (whistle)
- */
- lui t1,%hi(spurious_count)
- lw t0,%lo(spurious_count)(t1)
- la v0,return
- addiu t0,1
- jr ra
- sw t0,%lo(spurious_count)(t1)
- END(spurious_interrupt)
-
--- /dev/null
+/*
+ * linux/arch/mips/kernel/proc.c
+ *
+ * Copyright (C) 1995, 1996 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+
+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;
+}
* 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 <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.h>
#include <linux/mman.h>
#include <linux/sys.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <asm/bootinfo.h>
-#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
#include <asm/stackframe.h>
+#include <asm/uaccess.h>
#include <asm/io.h>
+#include <asm/elf.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#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;
/*
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));
}
/* 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 <linux/head.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/user.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/page.h>
#include <asm/system.h>
-#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)) {
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;
}
/*
* 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)) {
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)
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)
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;
}
*result = low;
} else
- *result = get_long(vma, addr);
+ *result = get_long(tsk, vma, addr);
return 0;
}
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;
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);
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;
-
- 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;
- }
- if (addr == EFL) { /* flags. */
- data &= FLAG_MASK;
- data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER) & ~FLAG_MASK;
+ res = write_long(child,addr,data);
+ goto out;
+
+ 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;
+ };
}
- /* 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;
}
/*
* 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)
* 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;
}
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sigcontext.h>
+
+ .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)
--- /dev/null
+/* $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 <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .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
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * 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
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+/* 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)
+
+
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sigcontext.h>
+
+ .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)
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/current.h>
+#include <asm/offset.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#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)
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .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
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/current.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+ .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)
+++ /dev/null
-/*
- * 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 <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/segment.h>
-#include <asm/stackframe.h>
-
-#ifdef __SMP__
-#error "Fix this for SMP"
-#else
-#define current current_set
-#endif
-
-MODE_ALIAS = 0x0016 # uncachable
-
- .text
- .set mips3
- .set noreorder
-
- .align 5
- NESTED(handle_tlbl, FR_SIZE, sp)
- .set noat
- /*
- * Check whether this is a refill or an invalid exception
- *
- * NOTE: Some MIPS manuals say that the R4x00 sets the
- * BadVAddr only when EXL == 0. This is wrong - BadVAddr
- * is being set for all Reload, Invalid and Modified
- * exceptions.
- */
- mfc0 k0,CP0_BADVADDR
- mfc0 k1,CP0_ENTRYHI
- ori k0,0x1fff
- xori k0,0x1fff
- andi k1,0xff
- or k0,k1
- mfc0 k1,CP0_ENTRYHI
- mtc0 k0,CP0_ENTRYHI
- nop # for R4[04]00 pipeline
- nop
- nop
- tlbp
- nop # for R4[04]00 pipeline
- nop
- mfc0 k0,CP0_INDEX
- bgez k0,invalid_tlbl # bad addr in c0_badvaddr
- mtc0 k1,CP0_ENTRYHI # delay slot
- /*
- * Damn... The next nop is required on my R4400PC V5.0, but
- * I don't know why - at least there is no documented
- * reason as for the others :-(
- */
- nop
-
-#ifdef CONF_DEBUG_TLB
- /*
- * OK, this is a double fault. Let's see whether this is
- * due to an invalid entry in the page_table.
- */
- dmfc0 k0,CP0_BADVADDR
- srl k0,12
- sll k0,2
- lui k1,%HI(TLBMAP)
- addu k0,k1
- lw k1,(k0)
- andi k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
- bnez k1,reload_pgd_entries
- nop # delay slot
-
- .set noat
- SAVE_ALL
- .set at
- PRINT("Double fault caused by invalid entries in pgd:\n")
- dmfc0 a1,CP0_BADVADDR
- PRINT("Double fault address : %08lx\n")
- dmfc0 a1,CP0_EPC
- PRINT("c0_epc : %08lx\n")
- jal show_regs
- move a0,sp
- jal dump_tlb_all
- nop
- dmfc0 a0,CP0_BADVADDR
- jal dump_list_current
- nop
- .set noat
- STI
- .set at
- PANIC("Corrupted pagedir")
- .set noat
-
-reload_pgd_entries:
-#endif /* CONF_DEBUG_TLB */
-
- /*
- * Load missing pair of entries from the pgd and return.
- */
- dmfc0 k1,CP0_CONTEXT
- dsra k1,1
- lwu k0,(k1) # Never causes nested exception
- lwu k1,4(k1)
- dsrl k0,6 # Convert to EntryLo format
- dsrl k1,6 # Convert to EntryLo format
- dmtc0 k0,CP0_ENTRYLO0
- dmtc0 k1,CP0_ENTRYLO1
- nop # for R4[04]00 pipeline
- tlbwr
- nop # for R4[04]00 pipeline
- nop
- nop
- /*
- * We don't know whether the original access was read or
- * write, so return and see what happens...
- */
- eret
-
- /*
- * Handle invalid exception
- *
- * There are two possible causes for an invalid (tlbl)
- * exception:
- * 1) pages with present bit set but the valid bit clear
- * 2) 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)
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sigcontext.h>
+
+ .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)
--- /dev/null
+/*
+ * linux/arch/mips/sni/process.c
+ *
+ * Reset the machine.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <asm/reboot.h>
+
+/*
+ * 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();
+}
* 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 <linux/config.h>
-#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.h>
#include <linux/user.h>
+#include <linux/utsname.h>
#include <linux/a.out.h>
#include <linux/tty.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#ifdef CONFIG_RTC
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#endif
#include <asm/asm.h>
#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/io.h>
#include <asm/vector.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
#include <asm/system.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#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.
+ * What to do to keep the caches consistent with memory
+ * We don't use the normal cacheflush routine to keep Tyne caches happier.
*/
-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);
+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.
- */
-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.
+ * 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.
*/
-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 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))
+{
+ panic("Unknown machtype in init_IRQ");
+}
+
+__initfunc(static void default_fd_cacheflush(const void *addr, size_t size))
{
- /* TBD */
- return 0;
}
-#endif /* 0 */
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+__initfunc(void setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p))
{
- unsigned long memory_start, memory_end;
+ 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 */
* linux/arch/mips/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996 Ralf Baechle
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
+#include <asm/asm.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/cachectl.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
#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;
}
/*
* 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
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 ...
* 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;
-
- frame->scc.sc_t8 = regs->reg24; /* Caller saved */
- frame->scc.sc_t9 = regs->reg25;
+ __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]);
- /*
- * 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 */
+ 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_epc = regs->cp0_epc; /* Program counter */
- frame->scc.sc_cause = regs->cp0_cause; /* c0_epc register */
+segv_and_exit:
+ lock_kernel();
+ do_exit(SIGSEGV);
+ unlock_kernel();
+}
- frame->scc.sc_oldmask = oldmask;
- *fp = frame;
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs * regs)
+{
+ setup_frame(sa, regs, signr, oldmask);
- regs->reg4 = signr; /* argument for handler */
+ 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);
+ }
}
+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
*/
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);
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;
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;
}
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;
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;
}
* 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 <linux/config.h>
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/unistd.h>
+#include <asm/branch.h>
#include <asm/ptrace.h>
-#include <asm/segment.h>
#include <asm/signal.h>
+#include <asm/uaccess.h>
extern asmlinkage void syscall_trace(void);
typedef asmlinkage int (*syscall_t)(void *a0,...);
-extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
- int narg);
+extern 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;
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;
}
/*
*/
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,<syscallno>" 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;
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)<pc=%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
{
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;
}
* 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
*/
/*
*
* 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)
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 */
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)
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/swap.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/times.h>
+#include <linux/elf.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+/* 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;
+}
#include <linux/utsname.h>
#include <asm/cachectl.h>
-#include <asm/segment.h>
+#include <asm/pgtable.h>
#include <asm/sysmips.h>
-
-static inline size_t
-strnlen_user(const char *s, size_t count)
-{
- return strnlen(s, count);
-}
+#include <asm/uaccess.h>
/*
* How long a hostname can we get from user space?
{
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;
{
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();
*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;
* found in some MIPS systems.
*/
#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/interrupt.h>
-#include <asm/segment.h>
+#include <asm/bootinfo.h>
+#include <asm/uaccess.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <linux/mc146818rtc.h>
#include <linux/timex.h>
-#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
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;
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)
xtime = *tv;
time_state = TIME_BAD;
- time_maxerror = 0x70000000;
- time_esterror = 0x70000000;
+ time_maxerror = MAXPHASE;
+ time_esterror = MAXPHASE;
sti();
}
/* 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
* 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);
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.
)*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;
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);
}
/*
- * 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
* 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 <linux/head.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
+#include <linux/config.h>
+#include <linux/init.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <asm/branch.h>
+#include <asm/cachectl.h>
+#include <asm/jazz.h>
#include <asm/vector.h>
-#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/io.h>
-#include <asm/mipsregs.h>
#include <asm/bootinfo.h>
+#include <asm/watch.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
+
+#undef CONF_DEBUG_EXCEPTIONS
static inline void console_verbose(void)
{
extern asmlinkage void deskstation_tyne_handle_int(void);
extern asmlinkage void mips_magnum_4000_handle_int(void);
-extern asmlinkage void handle_mod(void);
-extern asmlinkage void handle_tlbl(void);
-extern asmlinkage void handle_tlbs(void);
+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);
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;
*/
#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
}
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++)
}
else
printk("(Bad address in epc)\n");
-while(1);
do_exit(SIGSEGV);
}
-static void
-fix_ade(struct pt_regs *regs, int write)
+void die_if_kernel(const char * str, struct pt_regs * regs, long err)
{
- printk("Received address error (ade%c)\n", write ? 's' : 'l');
- panic("Fixing address errors not implemented yet");
-}
-
-void do_adel(struct pt_regs *regs)
-{
- if(current->tss.mflags & MF_FIXADE)
- {
- fix_ade(regs, 0);
+ /*
+ * 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, unsigned int fcr31)
+{
+ 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();
}
-void do_fpe(struct pt_regs *regs)
+static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
{
-show_regs(regs);
-while(1);
- send_sig(SIGFPE, current, 1);
+ 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;
+ }
+}
+
+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);
- if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
+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
/*
* 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();
}
+++ /dev/null
-/*
- * Deskstation Tyne specific C parts
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/*
- * How to access the FDC's registers.
- */
-unsigned char deskstation_tyne_fd_inb(unsigned int port)
-{
- return inb_p(port);
-}
-
-void deskstation_tyne_fd_outb(unsigned char value, unsigned int port)
-{
- outb_p(value, port);
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void deskstation_tyne_fd_enable_dma(void)
-{
- enable_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_disable_dma(void)
-{
- disable_dma(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_request_dma(void)
-{
- return request_dma(FLOPPY_DMA, "floppy");
-}
-
-void deskstation_tyne_fd_free_dma(void)
-{
- free_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_clear_dma_ff(void)
-{
- clear_dma_ff(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_set_dma_mode(char mode)
-{
- return set_dma_mode(FLOPPY_DMA, mode);
-}
-
-void deskstation_tyne_fd_set_dma_addr(unsigned int a)
-{
- set_dma_addr(FLOPPY_DMA, addr);
-}
-
-void deskstation_tyne_fd_set_dma_count(unsigned int count)
-{
- set_dma_count(FLOPPY_DMA, count);
-}
-
-int deskstation_tyne_fd_get_dma_residue(void)
-{
- return get_dma_residue(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_enable_irq(void)
-{
- enable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_disable_irq(void)
-{
- disable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_cacheflush(unsigned char *addr, unsigned int)
-{
- sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-
-/*
- * Tiny Tyne DMA buffer allocator
- *
- * Untested for a long time and changed again and again ...
- * Sorry, but no hardware to test ...
- */
-static unsigned long allocated;
-
-/*
- * Not very sophisticated, but should suffice for now...
- */
-unsigned long deskstation_tyne_dma_alloc(size_t size)
-{
- unsigned long ret = allocated;
- allocated += size;
- if (allocated > boot_info.dma_cache_size)
- ret = -1;
- return ret;
-}
-
-void deskstation_tyne_dma_init(void)
-{
- if (boot_info.machtype != MACH_DESKSTATION_TYNE)
- return;
- allocated = 0;
- printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
- boot_info.dma_cache_size >> 10);
-}
+++ /dev/null
-/*
- * arch/mips/kernel/tyne.S
- *
- * Deskstation Tyne specific Assembler code
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-/*
- * Deskstation Tyne interrupt handler
- */
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(deskstation_tyne_handle_int, FR_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- lui s0,%hi(PORT_BASE)
- li t1,0x0f
- sb t1,%lo(PORT_BASE+0x20)(s0) # poll command
- lb t1,%lo(PORT_BASE+0x20)(s0) # read result
- li s1,1
- bgtz t1,Lpoll_second
- andi t1,t1,7
- /*
- * Acknowledge first pic
- */
- lb t2,%lo(PORT_BASE+0x21)(s0)
- lui s4,%hi(cache_21)
- lb t0,%lo(cache_21)(s4)
- sllv s1,s1,t1
- or t0,t0,s1
- sb t0,%lo(cache_21)(s4)
- sb t0,%lo(PORT_BASE+0x21)(s0)
- lui s3,%hi(intr_count)
- lw t0,%lo(intr_count)(s3)
- li t2,0x20
- sb t2,%lo(PORT_BASE+0x20)(s0)
- /*
- * Now call the real handler
- */
- la t3,IRQ_vectors
- sll t2,t1,2
- addu t3,t3,t2
- lw t3,(t3)
- addiu t0,t0,1
- jalr t3
- sw t0,%lo(intr_count)(s3) # delay slot
- lw t0,%lo(intr_count)(s3)
- /*
- * Unblock first pic
- */
- lbu t1,%lo(PORT_BASE+0x21)(s0)
- lb t1,%lo(cache_21)(s4)
- subu t0,t0,1
- sw t0,%lo(intr_count)(s3)
- nor s1,zero,s1
- and t1,t1,s1
- sb t1,%lo(cache_21)(s4)
- jr v0
- sb t1,%lo(PORT_BASE+0x21)(s0) # delay slot
-
- .align 5
-Lpoll_second: li t1,0x0f
- sb t1,%lo(PORT_BASE+0xa0)(s0) # poll command
- lb t1,%lo(PORT_BASE+0xa0)(s0) # read result
- lui s4,%hi(cache_A1)
- bgtz t1,spurious_interrupt
- andi t1,t1,7
- /*
- * Acknowledge second pic
- */
- lbu t2,%lo(PORT_BASE+0xa1)(s0)
- lb t3,%lo(cache_A1)(s4)
- sllv s1,s1,t1
- or t3,t3,s1
- sb t3,%lo(cache_A1)(s4)
- sb t3,%lo(PORT_BASE+0xa1)(s0)
- li t3,0x20
- sb t3,%lo(PORT_BASE+0xa0)(s0)
- lui s3,%hi(intr_count)
- lw t0,%lo(intr_count)(s3)
- sb t3,%lo(PORT_BASE+0x20)(s0)
- /*
- * Now call the real handler
- */
- la t0,IRQ_vectors
- sll t2,t1,2
- addu t0,t0,t2
- lw t0,32(t0)
- addiu t0,t0,1
- jalr t0
- sw t0,%lo(intr_count)(s3) # delay slot
- lw t0,%lo(intr_count)(s3)
- /*
- * Unblock second pic
- */
- lb t1,%lo(PORT_BASE+0xa1)(s0)
- lb t1,%lo(cache_A1)(s4)
- subu t0,t0,1
- lw t0,%lo(intr_count)(s3)
- nor s1,zero,s1
- and t1,t1,s1
- sb t1,%lo(cache_A1)(s4)
- jr v0
- sb t1,%lo(PORT_BASE+0xa1)(s0) # delay slot
- END(deskstation_tyne_handle_int)
-
- .align 5
-LEAF(spurious_interrupt)
- /*
- * Nothing happened... (whistle)
- */
- lui t1,%hi(spurious_count)
- lw t0,%lo(spurious_count)(t1)
- la v0,return
- addiu t0,1
- jr ra
- sw t0,%lo(spurious_count)(t1)
- END(spurious_interrupt)
-
--- /dev/null
+/*
+ * 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 <sys/sysmips.h>
+ *
+ * ...
+ * 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 <stdio.h>
+ * #include <asm/sysmips.h>
+ *
+ * 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 <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+
+#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;
+}
*/
#include <linux/linkage.h>
#include <linux/errno.h>
-#include <linux/vm86.h>
-asmlinkage int sys_vm86(struct vm86_struct * v86)
+asmlinkage int sys_vm86(void *v86)
{
return -ENOSYS;
}
+++ /dev/null
-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) }
-}
--- /dev/null
+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) }
+}
--- /dev/null
+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) }
+}
#
# 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
$(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
*/
#include <net/checksum.h>
#include <asm/string.h>
+#include <asm/uaccess.h>
+
+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
+ unsigned long result = do_csum(buff, len);
- lw %2,-20(%5)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-16(%5)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-12(%5)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-8(%5)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-4(%5)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- bne %5,%1,1b
- addu %0,$1 # delay slot
-
-2: andi %1,%4,0x1c
- srl %1,%1,2
- beqz %1,4f
- addu %1,%5 # delay slot
-3: lw %2,0(%5)
- addu %5,4
- addu %0,%2
- sltu $1,%0,%2
- bne %5,%1,3b
- addu %0,$1 # delay slot
-
-4: andi $1,%3,2
- beqz $1,5f
- move %2,$0 # delay slot
- lhu %2,(%5)
- addiu %5,2
-
-5: andi $1,%3,1
- beqz $1,6f
- sll %1,16 # delay slot
- lbu %1,(%5)
- nop # NOP ALERT (spit, gasp)
-6: or %2,%1
- addu %0,%2
- sltu $1,%0,%2
- addu %0,$1
-7: .set at
- .set reorder"
- : "=r"(sum), "=r" (scratch1), "=r" (scratch2)
- : "0"(sum), "r"(len), "r"(buff)
- : "$1");
-
- return sum;
+ /* 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 ...
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);
+}
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+#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
+ * <asm/string.h> takes care of the return value in a way GCC can optimize.
+ */
+ .globl __memcpy
+__memcpy = __copy_user
--- /dev/null
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+/*
+ * 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)
--- /dev/null
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics,
+ * written by Ralf Baechle.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+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<last;i++)
+ {
+ write_32bit_cp0_register(CP0_INDEX, i);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoreorder\n\t"
+ "nop;nop;nop;nop\n\t"
+ "tlbr\n\t"
+ "nop;nop;nop;nop\n\t"
+ ".set\treorder\n\t"
+ ".set\tmips0\n\t");
+ pagemask = read_32bit_cp0_register(CP0_PAGEMASK);
+ entryhi = read_64bit_cp0_register(CP0_ENTRYHI);
+ entrylo0 = read_64bit_cp0_register(CP0_ENTRYLO0);
+ entrylo1 = read_64bit_cp0_register(CP0_ENTRYLO1);
+
+ if((entrylo0|entrylo1) & 2)
+ {
+ /*
+ * Only print entries in use
+ */
+ printk("\nIndex: %2d %08x", i, pagemask);
+
+ printk(" %08x %08x", (unsigned int)(entryhi >> 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++);
+ }
+}
--- /dev/null
+/*
+ * 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;
--- /dev/null
+/* 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 <asm/asm.h>
+#include <asm/regdef.h>
+
+#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
--- /dev/null
+/* linux/arch/mips/lib/memset.c
+ *
+ * This is from GNU libc.
+ */
+
+#include <linux/types.h>
+
+#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;
+}
--- /dev/null
+/* ----------------------------------------------------------------------
+ * 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 <linux/tty.h>
+#include <asm/bootinfo.h>
+
+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 <sigh> 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<size_x * (size_y-1); i++)
+ *(caddr++) = *(caddr + size_x);
+
+ blank last line
+
+ caddr = vram_addr + (size_x * (size_y-1));
+ for(i=0; i<size_x; i++)
+ *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
+*/
+ pmax_putch('\n');
+}
+
+void print_string(const unsigned char *str)
+{
+ unsigned char c;
+
+ if (console_needs_init)
+ init_console();
+/*
+ while((c = *str++))
+ switch(c)
+ {
+ case '\n':
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ break;
+
+ default:
+ print_char(cursor_x, cursor_y, c);
+ cursor_x++;
+ if(cursor_x == size_x)
+ {
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ }
+ break;
+ }
+*/
+ pmax_printf(str);
+
+}
+
+/* end of file */
--- /dev/null
+#include <asm/regdef.h>
+#include <asm/decstation.h>
+
+ .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
--- /dev/null
+/*
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <linux/errno.h>
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+/*
+ * 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
--- /dev/null
+/*
+ * linux/arch/mips/lib/tags.c
+ *
+ * Copyright (C) 1996 Stoned Elipot
+ */
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 <linux/tty.h>
+#include <asm/bootinfo.h>
+
+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<size_x * (size_y-1); i++)
+ *(caddr++) = *(caddr + size_x);
+
+ /* blank last line */
+
+ caddr = vram_addr + (size_x * (size_y-1));
+ for(i=0; i<size_x; i++)
+ *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
+}
+
+void print_string(const unsigned char *str)
+{
+ unsigned char c;
+
+ if (console_needs_init)
+ init_console();
+
+ while((c = *str++))
+ switch(c)
+ {
+ case '\n':
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ break;
+
+ default:
+ print_char(cursor_x, cursor_y, c);
+ cursor_x++;
+ if(cursor_x == size_x)
+ {
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ }
+ break;
+ }
+}
+
+/* end of file */
--- /dev/null
+/*
+ * Kernel debug stuff to use the Watch registers.
+ * Usefull to find stack overflows, dangeling pointers etc.
+ *
+ * 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 <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+ .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)
# 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
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+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();
+}
--- /dev/null
+/*
+ * linux/arch/mips/mm/extable.c
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+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;
+}
/*
* arch/mips/mm/fault.c
*
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
-#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
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)
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();
}
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/swap.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
+#include <asm/bootinfo.h>
#include <asm/cachectl.h>
+#include <asm/dma.h>
#include <asm/jazzdma.h>
#include <asm/vector.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#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
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
*/
".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"
{
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
*/
"=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"
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)
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;
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++;
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);
}
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));
{
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))
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+
+/* 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.");
+ }
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+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();
+}
--- /dev/null
+/*
+ * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/autoconf.h>
+
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+/* 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 <asm/cacheops.h>
+#include <asm/r4kcache.h>
+
+#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();
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cacheops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+__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();
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+
+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();
+}
+
--- /dev/null
+# $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
--- /dev/null
+/* $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 <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ /* 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)
--- /dev/null
+/* $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 <asm/addrspace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/sgialib.h>
+
+/* #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;
+}
--- /dev/null
+/* $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 <linux/config.h>
+
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/vector.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgi.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/sgialib.h>
+
+/* #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
+}
--- /dev/null
+/* $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 <asm/addrspace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgialib.h>
+
+/* #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 */
+}
--- /dev/null
+/* $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 <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+/* 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();
+}
+
--- /dev/null
+/*
+ * linux/arch/mips/sgi/kernel/process.c
+ *
+ * Reset a SGI.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+
+/* 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 */
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/reboot.h>
+#include <asm/vector.h>
+#include <asm/sgialib.h>
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+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();
+ }
+ }
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+#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");
+}
--- /dev/null
+/* $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();
+}
--- /dev/null
+# $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
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+/* #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
+}
--- /dev/null
+/* $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 <asm/sgialib.h>
+
+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;
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+
+char *prom_getenv(char *name)
+{
+ return romvec->get_evar(name);
+}
+
+long prom_setenv(char *name, char *value)
+{
+ return romvec->set_evar(name, value);
+}
--- /dev/null
+/* $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 <asm/sgialib.h>
+
+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);
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+
+#include <asm/sgialib.h>
+
+/* #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;
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+
+#include <asm/sgialib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+
+/* #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<<PAGE_SHIFT) + 0x80000000);
+ prom_pblocks[i].size = p->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;
+ }
+}
--- /dev/null
+/*
+ * misc.c: Miscellaneous ARCS PROM routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+
+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();
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+
+#include <asm/sgialib.h>
+
+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;
+}
--- /dev/null
+/* $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 <asm/sgialib.h>
+
+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);
+}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/addrspace.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/sgimc.h>
+
+/* 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 */
+}
--- /dev/null
+/* $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 <asm/sgialib.h>
+
+struct linux_tinfo *prom_gettinfo(void)
+{
+ return romvec->get_tinfo();
+}
+
+unsigned long prom_getrtime(void)
+{
+ return romvec->get_rtime();
+}
--- /dev/null
+/* $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 <asm/sgialib.h>
+
+#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
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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 <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mc146818rtc.h>
+#include <asm/pgtable.h>
+#include <asm/vector.h>
+
+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
+};
--- /dev/null
+/*
+ * SNI RM200 PCI specific interrupt handler code.
+ *
+ * Copyright (C) 1994 - 1997 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <linux/config.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sni.h>
+#include <asm/stackframe.h>
+
+ .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)
--- /dev/null
+/*
+ * 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 <linux/string.h>
+#include <asm/mipsconfig.h>
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+#include <asm/sni.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#include <linux/bios32.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/pci.h>
+#include <asm/sni.h>
+
+#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 */
--- /dev/null
+/*
+ * linux/arch/mips/sni/process.c
+ *
+ * Reset a SNI machine.
+ */
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/sni.h>
+
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 <asm/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/sni.h>
+#include <asm/vector.h>
+#include <asm/pci.h>
+
+/*
+ * 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;
+}
--- /dev/null
+# 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
--- /dev/null
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Made portable by Ralf Baechle
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+#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) */");
-# $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.
#
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
CONFIG_BINFMT_JAVA=m
#
# 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)
-# $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.
#
# 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
#
# 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
#
# 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)
#
#
#
-# 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
#
# 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
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
-# $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
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
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB;
+#define elf_check_arch(x) (((x) == EM_SPARC) || ((x) == EM_SPARC32PLUS))
+
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/config.h>
-/* $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)
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
-/* $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)
#include <linux/kd.h>
#include <linux/route.h>
#include <linux/netlink.h>
+#include <linux/vt.h>
+#include <linux/fs.h>
#include <asm/types.h>
#include <asm/uaccess.h>
+#include <asm/fbio.h>
+#include <asm/kbio.h>
+#include <asm/vuid_event.h>
+#include <asm/rtc.h>
/* 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.
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;
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...
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:
case FIONBIO:
case FIONREAD: /* This is also TIOCINQ */
+ /* 0x00 */
+ case FIBMAP:
+ case FIGETBSZ:
+
/* 0x12 */
case BLKRRPART:
case BLKFLSBUF:
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:
-/* $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)
}
/* 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;
*/
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)
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;
-/* $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)
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
-/* $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
}
#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;
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 ();
}
__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));
}
__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);
-/* $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)
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);
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)
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;
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;
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;
}
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);
{
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;
-}
-/* $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.
*
/*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
/*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
/*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
/*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
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/asi.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#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
-/* $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)
#include <asm/asi.h>
+#undef VIS_BLOCKOPS
+
/* Zero out 256 bytes of memory at (buf + offset). */
#define BLAST_BLOCK(buf, offset) \
stda %f48, [buf + offset + 0x00] %asi; \
.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
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
#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
#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"
#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
/* 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; \
-/* $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)
/* #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 <asm/hardirq.h>
+
asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write,
unsigned long address, unsigned long tag,
unsigned long sfsr)
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);
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
}
-/* $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)
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);
}
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 */
- ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0);
#ifdef CONFIG_BLK_DEV_OPTI621
ide_probe_pci (PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, &ide_init_opti621, 0);
#endif /* CONFIG_BLK_DEV_OPTI621 */
+Thu Jun 19 20:05:58 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * 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 <tytso@rsts-11.mit.edu>
+
+ * 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 <tytso@rsts-11.mit.edu>
* serial.c (change_speed): Add support for the termios flag
__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;
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;
}
* 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;
* 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;
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;
}
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;
}
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)
nr = video_num_lines;
else if (!nr)
nr=1;
- while (nr--)
- delete_line(currcons);
+ delete_line(currcons, nr);
}
static void save_cur(int currcons)
/*
* 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;
}
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);
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;
}
if (O_OPOST(tty) && !(tty->flags & (1<<TTY_HW_COOK_OUT))) {
while (nr > 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;
/*
* 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.
*
* 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 ) ) )
(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];
/* 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<<HASH_BITS)-1)) + (count << HASH_BITS);
+
/*
* As close as possible to RFC 793, which
* suggests using a 250kHz clock.
- * Further reading shows this assumes 2MB/s networks.
- * For 10MB/s ethernet, a 1MHz clock is appropriate.
+ * Further reading shows this assumes 2Mb/s networks.
+ * For 10Mb/s ethernet, a 1MHz clock is appropriate.
* That's funny, Linux has one built in! Use it!
+ * (Networks are faster now - should this be increased?)
*/
- seq = (tmp[1]&0xFFFFFF) + (tv.tv_usec+tv.tv_sec*1000000) +
- (count << 24);
+ seq += tv.tv_usec + tv.tv_sec*1000000;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
#endif
- return (seq);
+ return seq;
+}
+
+#ifdef CONFIG_SYN_COOKIES
+/*
+ * Secure SYN cookie computation. This is the algorithm worked out by
+ * Dan Bernstein and Eric Schenk.
+ *
+ * For linux I implement the 1 minute counter by looking at the jiffies clock.
+ * The count is passed in as a parameter;
+ *
+ */
+__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport, __u32 sseq, __u32 count)
+{
+ static int is_init = 0;
+ static __u32 secret[2][16];
+ __u32 tmp[16];
+ __u32 seq;
+
+ /*
+ * Pick two random secret the first time we open a TCP connection.
+ */
+ if (is_init == 0) {
+ get_random_bytes(&secret[0], sizeof(secret[0]));
+ get_random_bytes(&secret[1], sizeof(secret[1]));
+ is_init = 1;
+ }
+
+ /*
+ * Compute the secure sequence number.
+ * The output should be:
+ * MD5(sec1,saddr,sport,daddr,dport,sec1) + their sequence number
+ * + (count * 2^24)
+ * + (MD5(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
+ * Where count increases every minute by 1.
+ */
+
+ memcpy(tmp, secret[0], sizeof(tmp));
+ tmp[8]=saddr;
+ tmp[9]=daddr;
+ tmp[10]=(sport << 16) + dport;
+ HASH_TRANSFORM(tmp, tmp);
+ seq = tmp[1];
+
+ memcpy(tmp, secret[1], sizeof(tmp));
+ tmp[8]=saddr;
+ tmp[9]=daddr;
+ tmp[10]=(sport << 16) + dport;
+ tmp[11]=count; /* minute counter */
+ HASH_TRANSFORM(tmp, tmp);
+
+ seq += sseq + (count << 24) + (tmp[1] & 0x00ffffff);
+
+ /* Zap lower 3 bits to leave room for the MSS representation */
+ return (seq & 0xfffff8);
}
+#endif
+
#ifdef RANDOM_BENCHMARK
/*
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);
#endif
}
+/*
+ * 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.
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);
case TIOCSSOFTCAR:
* 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 <Marko.Kohtala@hut.fi>, March 97
+ *
+ * Rewrote init_dev and release_dev to eliminate races.
+ * -- Bill Hawes <whawes@star.net>, June 97
*/
#include <linux/config.h>
#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 */
(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);
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];
- 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) {
+ if (driver->type == TTY_DRIVER_TYPE_PTY) {
+ 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;
+
+ 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;
- }
+ 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 = 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;
- }
- (*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;
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",
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;
}
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]) {
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) {
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);
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);
}
/*
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 &&
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);
#
-# $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
#
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
#
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
endif
endif
+ifeq ($(CONFIG_SGISEEQ), y)
+L_OBJS += sgiseeq.o
+endif
+
ifeq ($(CONFIG_HAPPYMEAL),y)
L_OBJS += sunhme.o
else
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
endif
endif
+ifeq ($(CONFIG_COPS),y)
+L_OBJS += cops.o
+else
+ ifeq ($(CONFIG_COPS),m)
+ M_OBJS += cops.o
+ endif
+endif
+
ifeq ($(CONFIG_BAYCOM),y)
L_OBJS += baycom.o
CONFIG_HDLCDRV_BUILTIN = y
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 *);
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 *);
&& sparc_lance_probe(dev)
#endif
#ifdef CONFIG_HAPPYMEAL
- && happy_meal_probe(dev)
+ && happy_meal_probe(dev)
#endif
#ifdef CONFIG_SUNQE
&& qec_probe(dev)
#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. */
}
# 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
# define ETH0_ADDR 0
--- /dev/null
+/* cops.c: LocalTalk driver for Linux.
+ *
+ * Authors:
+ * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *
+ * With more than a little help from;
+ * - Alan Cox <Alan.Cox@linux.org>
+ *
+ * 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 <Jay.Schulist@spacs.k12.wi.us>\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 <linux/module.h>
+#include <linux/version.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/if_arp.h>
+#include <linux/if_ltalk.h> /* For ltalk_setup() */
+#include <linux/delay.h> /* For udelay() */
+#include <linux/atalk.h>
+
+#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 <johns393@maroon.tc.umn.edu>
+ * 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-snap<HZ/3)
+ schedule();
+ }
+ else
+ udelay(333333);
+ }
+ dev->tbusy=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 */
--- /dev/null
+/* cops.h: LocalTalk driver for Linux.
+ *
+ * Authors:
+ * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ */
+
+#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
--- /dev/null
+
+/*
+ * 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 <Jay.Schulist@spacs.k12.wi.us>
+ */
+
+
+#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
--- /dev/null
+/*
+ * 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 <Jay.Schulist@spacs.k12.wi.us>
+ */
+
+
+#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
return 0;
}
-__initfunc(static int lapbeth_dev_init(struct device *dev))
+static int lapbeth_dev_init(struct device *dev)
{
return 0;
}
--- /dev/null
+/* $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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
+#include <linux/socket.h>
+#include <linux/route.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/sgihpc.h>
+#include <asm/sgialib.h>
+
+#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);
+
+}
--- /dev/null
+/* $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) */
--- /dev/null
+/*
+ * 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 <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#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;
+}
+
+\f
+/*
+ * 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; i<SONIC_NUM_RDS; i++) {
+ lp->rda[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);
+}
+
+\f
+/*
+ * 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:
+ */
--- /dev/null
+/*
+ * 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 */
-/* $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)
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;
-/* $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)
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);
-/* $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)
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)
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;
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:
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) {
-/* $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)
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)
-/* $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.
*
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);
-/* $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)
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)
-/* $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.
*
(*fb_restore_palette) (&fbinfo[0]);
}
-unsigned int
+unsigned long
get_phys (unsigned long addr)
{
return __get_phys(addr);
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];
-/* $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)
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);
__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;
}
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++){
__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;
}
-/* $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)
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 };
-/* $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)
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)
static struct file_system_type autofs_fs_type = {
"autofs",
- FS_NO_DCACHE,
+ 0 /* FS_NO_DCACHE doesn't work correctly */,
autofs_read_super,
NULL
};
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;
}
*/
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);
/* 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 */
/*
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");
static struct file_system_type ncp_fs_type = {
"ncpfs",
- FS_NO_DCACHE,
+ 0 /* FS_NO_DCACHE doesn't work correctly */,
ncp_read_super,
NULL
};
*/
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
};
static struct file_system_type proc_fs_type = {
"proc",
- FS_NO_DCACHE,
+ 0 /* FS_NO_DCACHE doesn't work correctly */,
proc_read_super,
NULL
};
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
};
static struct file_system_type smb_fs_type = {
"smbfs",
- FS_NO_DCACHE,
+ 0 /* FS_NO_DCACHE doesn't work correctly */,
smb_read_super,
NULL
};
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
quota_off(dev, -1);
if (!fs_may_umount(dev, sb->s_mounted))
return -EBUSY;
+
+ /* Clear up the dcache tree. This should be cleaner.. */
+ while (sb->s_ibasket)
+ free_ibasket(sb);
+ if (sb->s_mounted->i_dentry)
+ d_del(sb->s_mounted->i_dentry, D_NO_CLEAR_INODE);
+
sb->s_covered->i_mount = NULL;
iput(sb->s_covered);
sb->s_covered = NULL;
#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
#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
#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 <asm-i386/errno.h> */
#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
--- /dev/null
+/*
+ * 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 */
* 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
*
#ifndef __ASM_ASM_H
#define __ASM_ASM_H
-#include <linux/config.h>
-#include <asm/regdef.h>
-#include <asm/fpregdef.h>
+#include <asm/sgidefs.h>
#ifndef CAT
#ifdef __STDC__
#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
*/
#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)
* 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
#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) \
#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)
-#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)
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
#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 */
--- /dev/null
+/* $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 <asm/offset.h>
+
+#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) */
--- /dev/null
+/*
+ * 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 <asm/sgidefs.h>
+
+/*
+ * 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 <asm/system.h>
+
+/*
+ * 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 */
* 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 <asm/sgidefs.h>
+#include <asm/system.h>
/*
- * These functions for MIPS ISA >= 2 are interrupt and SMP proof and
+ * 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 > 1 are interrupt and SMP proof and
* interrupt friendly
*/
#include <asm/mipsregs.h>
/*
* 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;
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;
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;
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 <asm/system.h>
+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;
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;
/*
* 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..
unsigned int __res;
unsigned int mask = 1;
- __asm__ __volatile__ (
+ __asm__ (
".set\tnoreorder\n\t"
".set\tnoat\n\t"
"move\t%0,$0\n"
".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 */
/*
* 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
#ifndef __ASM_MIPS_BOOTINFO_H
#define __ASM_MIPS_BOOTINFO_H
+/* XXX */
+#include <linux/config.h>
+
+#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_DESKSTATION_RPC44 0 /* Deskstation rPC44 */
+#define MACH_DESKSTATION_TYNE 1 /* Deskstation Tyne */
+
+#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_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_ACN_MIPS_BOARD 0 /* ACN MIPS single board */
+
+#define GROUP_ACN_NAMES { "ACN" }
-#define MACH_NAMES { "unknown", "Deskstation rPC44", "Deskstation Tyne", \
- "Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" }
+/*
+ * Valid machtype for group SGI
+ */
+#define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstaions */
/*
* Valid cputype values
#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;
- /*
- * TLB Info
- */
- tlb_entries,
+/* macros for parsing tag list */
+#define TAGVALPTR(t) ((void*)(((void*)(t)) - ((t)->size)))
+#define NEXTTAGPTR(t) ((void*)(TAGVALPTR(t) - (sizeof(tag))))
- /*
- * DMA buffer size (Deskstation only)
- */
- dma_cache_size,
- dma_cache_base,
+/* 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])
- /*
- * Ramdisk Info
- */
- ramdisk_size, /* ramdisk size in 1024 byte blocks */
- ramdisk_base, /* address of the ram disk in mem */
+/*
+ * For tag readers aka the kernel
+ */
+tag *bi_TagFind(enum bi_tag type);
+void bi_EarlySnarf(void);
- /*
- * Boot flags for the kernel
- */
- mount_root_rdonly,
- drive_info,
+/* 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);
- /*
- * Video ram info (not in tty.h)
- */
- vram_base, /* video ram base address */
-
- command_line /* kernel command line parameters */
-
-};
-typedef struct {
- bi_tag tag;
- unsigned long size;
-} tag;
-#endif
+#ifdef CONFIG_SGI
-extern struct bootinfo boot_info;
+/* 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,}}
-/*
- * 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
+
+/* 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,}}
+
+#endif
-#else /* !__LANGUAGE_ASSEMBLY__ */
/*
- * Same structure, but as offsets for usage within assembler source.
- * Don't mess with struct bootinfo without changing offsets too!
+ * 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
*/
-
-#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
+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__ */
--- /dev/null
+/*
+ * 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 <asm/ptrace.h>
+
+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;
+}
* 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;
+/*
+ * 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);
+#define __constant_ntohl(x) __swap32(x)
+#define __constant_ntohs(x) __swap16(x)
+#define __constant_htonl(x) __swap32(x)
+#define __constant_htons(x) __swap16(x)
-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);
+#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)
+{
+ return __constant_ntohs(__x);
+}
-extern __inline__ unsigned short int
-__ntohs(unsigned short int x)
+extern __inline__ unsigned long int htonl(unsigned long int __x)
{
- return (((x & 0x00ff) << 8) |
- ((x & 0xff00) >> 8));
+ return __constant_htonl(__x);
}
-#define __constant_ntohs(x) \
- ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
- (((unsigned short int)(x) & 0xff00) >> 8))) \
-
-#define __htonl(x) __ntohl(x)
-#define __htons(x) __ntohs(x)
-#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 */
/*
* 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 */
/*
- * 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 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 */
--- /dev/null
+/*
+ * 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 */
* 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.
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);
}
/*
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;
unsigned short proto,
unsigned int sum)
{
- unsigned long scratch;
-
- __asm__("
+ __asm__("
.set noreorder
.set noat
addu %0,%5 # proto (long in network byte order)
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");
--- /dev/null
+/* $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) */
-#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 */
--- /dev/null
+/*
+ * 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 */
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));
* 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
* range of numbers that appears for MIPS machines avoids overflows.
--- /dev/null
+/*
+ * 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 */
* 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 <asm/io.h> /* need byte IO */
+#include <linux/config.h>
+#include <asm/io.h> /* need byte IO */
#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
#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 */
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 */
#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];
/*
* 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 */
#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 /* ??? */
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;
#ifndef __ASM_MIPS_FLOPPY_H
#define __ASM_MIPS_FLOPPY_H
+#include <linux/config.h>
#include <asm/bootinfo.h>
#include <asm/jazz.h>
#include <asm/jazzdma.h>
#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)
#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;
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? */
--- /dev/null
+#ifndef __ASM_MIPS_HARDIRQ_H
+#define __ASM_MIPS_HARDIRQ_H
+
+#include <linux/tasks.h>
+
+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 */
--- /dev/null
+/*
+ * 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 */
-#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... */
#define __FINIT
#define __INITDATA
-#endif
+#endif /* __ASM_MIPS_INIT_H */
--- /dev/null
+/*
+ * 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 */
#ifndef __ASM_MIPS_IO_H
#define __ASM_MIPS_IO_H
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
+
#include <asm/mipsconfig.h>
-#include <asm/segment.h>
+#include <asm/addrspace.h>
/*
* 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
*
* I feel a bit unsafe about using 0x80 (should be safe, though)
*
* Linus
+ *
*/
#define __SLOW_DOWN_IO \
"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.
*/
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..
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; } \
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" \
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"
+/*
+ * 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
+/*
+ * 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 <asm/ioctl.h>
+#if defined(__USE_MISC) || defined (__KERNEL__)
+#define tIOC ('t' << 8)
+#endif
+
#define TCGETA 0x5401
#define TCSETA 0x5402
#define TCSETAW 0x5403
#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 */
#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 */
#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 */
--- /dev/null
+#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 */
/*
* 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);
*
* This file is a mess. It really needs some reorganisation!
*/
-
#ifndef __ASM_MIPS_JAZZ_H
#define __ASM_MIPS_JAZZ_H
#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
*/
#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
#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 */
/*
* 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);
#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)
#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 */
/*
- * 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 <linux/config.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
#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 <asm/io.h>
+
+/*
+ * 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 <asm/segment.h>
+#include <asm/sgihpc.h>
+#endif
+#include <asm/bootinfo.h>
+#include <asm/jazz.h>
+
+#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 */
+
+/*
+ * 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);
+}
-#endif /* __KERNEL__ */
+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 */
#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
/*
* 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 */
* 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
* 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 */
--- /dev/null
+#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 */
* 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 <linux/linkage.h>
+
/*
* The following macros are especially useful for __asm__
* inline assembler.
*/
-
#ifndef __STR
#define __STR(x) #x
#endif
#define STR(x) __STR(x)
#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_TAGHI $29
#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
*/
: "=r" (__res)); \
__res;})
+/*
+ * For now use this only with interrupts disabled!
+ */
#define read_64bit_cp0_register(source) \
({ int __res; \
__asm__ __volatile__( \
/*
* 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) \
({ \
__asm__ __volatile__( \
"ll\t%0,(%1)" \
: "=r" (__res) \
- : "r" ((unsigned int) (addr))); \
+ : "r" ((unsigned long) (addr))); \
\
__res; \
})
})
/*
- * 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 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_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_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.
#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 */
#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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * linux/include/asm-mips/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+#ifndef __ASM_MIPS_NAMEI_H
+#define __ASM_MIPS_NAMEI_H
+
+#include <linux/config.h>
+
+#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 */
--- /dev/null
+/* 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) */
+/*
+ * 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
#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..
#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 */
--- /dev/null
+/*
+ * 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 */
#ifndef __ASM_MIPS_PGTABLE_H
#define __ASM_MIPS_PGTABLE_H
+#include <asm/addrspace.h>
+#include <asm/mipsconfig.h>
+
#ifndef __LANGUAGE_ASSEMBLY__
#include <linux/linkage.h>
#include <asm/cachectl.h>
-/*
- * The Linux memory management assumes a three-level page table setup. In
- * 32 bit mode we use that, but "fold" the mid level into the top-level page
- * table, so that we physically have the same two-level page table as the
- * i386 mmu expects. The 64 bit version uses a three level setup.
- *
- * This file contains the functions and defines necessary to modify and use
- * the MIPS page table tree. Note the frequent conversion between addresses
- * in KSEG0 and KSEG1.
+/* 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
*/
-
-/*
- * 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
+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 flushing:
*
- * FIXME: MIPS has full control of all TLB activity in the CPU. Though
- * we just stick with complete flushing of TLBs for now.
+ * - 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 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.
+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__) */
#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
#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 */
#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)
#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.
* 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))
#define PTR_MASK (~(sizeof(void*)-1))
/*
- * sizeof(void*)==1<<SIZEOF_PTR_LOG2
+ * sizeof(void*) == (1 << SIZEOF_PTR_LOG2)
*/
-#if __mips == 3
-#define SIZEOF_PTR_LOG2 3
-#else
#define SIZEOF_PTR_LOG2 2
-#endif
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+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)
-
-extern unsigned long high_memory;
+#define SET_PAGE_DIR(tsk,pgdir) (tsk)->tss.pg_dir = ((unsigned long) (pgdir))
+
extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
/*
* 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; }
+
+/* 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)
+{
+ *ptep = pteval;
+}
-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)
+extern inline void pte_clear(pte_t *ptep)
{
- if (!mem_map[MAP_NR(ptep)].reserved)
- mem_map[MAP_NR(ptep)].count++;
+ 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;
+ 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);
}
-extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_PRESENT; }
-extern inline int pmd_inuse(pmd_t *pmdp) { return 0; }
-extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
-extern inline void pmd_reuse(pmd_t * pmdp) { }
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
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;
pte_val(pte) |= _PAGE_SILENT_WRITE;
return pte;
}
+
extern inline pte_t pte_mkread(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
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;
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;
+extern void (*pgd_init)(unsigned long page);
- page += (PT_OFFSET - PAGE_OFFSET);
-#if __mips >= 3
- /*
- * Ich will Spass - ich geb Gas ich geb Gas...
- */
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- ".set\tmips3\n\t"
- "dsll32\t$1,%2,0\n\t"
- "dsrl32\t%2,$1,0\n\t"
- "or\t%2,$1\n"
- "1:\tsd\t%2,(%0)\n\t"
- "subu\t%1,1\n\t"
- "bnez\t%1,1b\n\t"
- "addiu\t%0,8\n\t"
- ".set\tmips0\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1),
- "=r" (dummy2)
- :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
- _PAGE_TABLE),
- "0" (page),
- "1" (PAGE_SIZE/(sizeof(pmd_t)*2))
- :"$1");
-#else
- __asm__ __volatile__(
- ".set\tnoreorder\n"
- "1:\tsw\t%2,(%0)\n\t"
- "subu\t%1,1\n\t"
- "bnez\t%1,1b\n\t"
- "addiu\t%0,4\n\t"
- ".set\treorder"
- :"=r" (dummy1),
- "=r" (dummy2)
- :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
- _PAGE_TABLE),
- "0" (page),
- "1" (PAGE_SIZE/sizeof(pmd_t)));
-#endif
-}
-
-extern inline pgd_t * pgd_alloc(void)
+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;
+}
+
+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;
+
+ __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));
+}
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+/* 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;
+}
-#endif
+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__) */
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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 <stddef.h>
+
+/*
+ * 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 */
*
* 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
*/
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.
/*
* 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)
*/
struct mips_fpu_soft_struct {
long dummy;
- };
+};
union mips_fpu_union {
struct mips_fpu_hard_struct hard;
* 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 }
*/ \
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 */
* 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.
#ifndef __ASM_MIPS_PTRACE_H
#define __ASM_MIPS_PTRACE_H
+#include <linux/types.h>
+
+#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 <asm/offset.h>
+
#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 */
--- /dev/null
+/* $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 <asm/cacheops.h>
+
+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) */
--- /dev/null
+/*
+ * 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 */
/*
- * 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
* 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
-/*
- * 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)
+#define EF_CP0_EPC 42
+#define EF_CP0_BADVADDR 43
+#define EF_CP0_STATUS 44
+#define EF_CP0_CAUSE 45
-/*
- * 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 */
* 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
/*
* 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__
-#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 */
#define ISA_DMA_THRESHOLD (0x00ffffff)
-#endif /* !(_MIPS_SCATTERLIST_H) */
+#endif /* __ASM_MIPS_SCATTERLIST_H */
-/*
- * 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 <linux/string.h>
+/* 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
--- /dev/null
+/*
+ * 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 <asm/atomic.h>
+
+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 */
--- /dev/null
+/* $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) */
--- /dev/null
+/* $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 <asm/sgiarcs.h>
+
+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) */
--- /dev/null
+/* $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) */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/* $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 <asm/page.h>
+
+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) */
--- /dev/null
+/* $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) */
--- /dev/null
+/* $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) */
#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 */
#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<isa>/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 */
-#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 <linux/types.h>
-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 <asm/sgidefs.h>
+
+/* 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.
*/
#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
*/
#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
};
#include <asm/sigcontext.h>
#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) */
+++ /dev/null
-/*
- * 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 */
--- /dev/null
+#ifndef __ASM_MIPS_SMP_H
+#define __ASM_MIPS_SMP_H
+
+/* We'll get here eventually.. */
+
+#endif /* __ASM_MIPS_SMP_H */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
#define __ASM_MIPS_SOCKET_H
#include <linux/types.h>
-#include <asm/ioctl.h>
-
-/* Socket-level I/O control calls. */
-#define FIOGETOWN _IOR('f', 123, int)
-#define FIOSETOWN _IOW('f', 124, int)
-
-#define SIOCATMARK _IOR('s', 7, int)
-#define SIOCSPGRP _IOW('s', 8, pid_t)
-#define SIOCGPGRP _IOR('s', 9, pid_t)
-
-#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */
+#include <asm/sockios.h>
/*
* For setsockoptions(2)
*/
#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_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
-#define SO_ERROR 0x1007
-#define SO_SNDBUF 0x1001
-#define SO_RCVBUF 0x1002
+#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 */
--- /dev/null
+/*
+ * 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 <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN _IOR('f', 123, int)
+#define FIOSETOWN _IOW('f', 124, int)
+
+#define SIOCATMARK _IOR('s', 7, int)
+#define SIOCSPGRP _IOW('s', 8, pid_t)
+#define SIOCGPGRP _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */
+
+#endif /* __ASM_MIPS_SOCKIOS_H */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
/*
* 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 <asm/asm.h>
+#include <asm/offset.h>
-/*
- * $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 */
#include <linux/types.h>
-struct old_stat {
+struct __old_kernel_stat {
unsigned int st_dev;
unsigned int st_ino;
unsigned int st_mode;
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;
+/*
+ * 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 <linux/posix_types.h>
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+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 */
* 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"
"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;
"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;
"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 */
#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 */
* 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 <asm/sgidefs.h>
#include <linux/kernel.h>
-#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" \
"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);
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);
* 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__(
".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;
*/
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:
+/*
+ * 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 <asm/ioctl.h>
-#include <asm/ioctls.h>
+#include <linux/posix_types.h>
+
+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 */
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 */
+/*
+ * 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 <linux/types.h>
#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+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;
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 <linux/string.h>
+
/*
* 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; \
(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 */
* 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
#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 */
--- /dev/null
+/*
+ * 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 <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/asm.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <asm/string.h>
+
+/*
+ * 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 */
* 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 ...
*/
/*
#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)
#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__
__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; \
"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)
/*
* 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
* 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) */
* 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.
*/
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 */
--- /dev/null
+/*
+ * 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 <linux/linkage.h>
+
+/*
+ * 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
#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
-/* $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
#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){
#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
#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__ */
-/* $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)
#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;
}
-/* $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
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; }
-/* $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
/*
* 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
};
#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;
#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 */
+++ /dev/null
-/* $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 <linux/sched.h>
-
-/* 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 */
-/* $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
#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;
#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;
-/* $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 <asm/ioctl.h>
-/* 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)
/* 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)
-/* $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
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;
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__) */
-/* $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
#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
-/* $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)
#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)
#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
1:
stxa %%g0, [%%g3] %3
stxa %%g0, [%%g3] %4
- be,a,pt %%icc, 1f
+ be,pt %%icc, 1f
nop
stxa %%g2, [%%g7] %2
1:
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);
1:
stxa %%g0, [%%g3] %3
stxa %%g0, [%%g3] %4
- be,a,pt %%icc, 1f
+ be,pt %%icc, 1f
nop
stxa %%g2, [%%g7] %2
1:
{ pte_t pte; pte_val(pte) = (type<<PAGE_SHIFT)|(offset<<(PAGE_SHIFT+8)); return pte; }
extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
-{ pte_t pte; pte_val(pte) = (page) | pgprot_val(prot); return pte; }
+{ pte_t pte; pte_val(pte) = ((page) | pgprot_val(prot) | _PAGE_E) & ~(unsigned long)_PAGE_CACHE; return pte; }
#define SWP_TYPE(entry) (((entry>>PAGE_SHIFT) & 0xff))
#define SWP_OFFSET(entry) ((entry) >> (PAGE_SHIFT+8))
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
-/* $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)
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;
"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)
-/* $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)
#define RLIM_NLIMITS 10
#ifdef __KERNEL__
-/* XXX 32-bit binary compatability... */
#define INIT_RLIMITS \
{ \
{LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \
-/* $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 <asm/ptrace.h>
-/* 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__
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.
-/* $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
{
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;
}
-/* $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
*
* "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)
-/* $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
#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 */
#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 */
/* #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 */
#endif /* __KERNEL_SYSCALLS__ */
+#ifdef __KERNEL__
/* sysconf options, for SunOS compatibility */
#define _SC_ARG_MAX 1
#define _SC_CHILD_MAX 2
#define _SC_JOB_CONTROL 6
#define _SC_SAVED_IDS 7
#define _SC_VERSION 8
+#endif
#endif /* _SPARC64_UNISTD_H */
*/
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) */
*/
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);
#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 */
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 */
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;
{
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;
}
#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
NET_IPV4_IGMP_AGE_THRESHOLD,
NET_TCP_SYNCOOKIES,
NET_TCP_ALWAYS_SYNCOOKIE,
+ NET_TCP_STDURG,
};
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);
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
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);
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 *);
return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
}
-
#undef STATE_TRACE
#ifdef STATE_TRACE
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);
*/
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);
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;
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;
+}
+
/*
* "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
* 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.
#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)
#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 */
#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;
{
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. */
#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;
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;
}
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) {
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.
*/
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;
}
/* (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);
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) {
*(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);
}
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 */
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
{
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
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)
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);
* 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
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),
if (jiffies - rt->last_error > (RT_REDIRECT_LOAD<<rt->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);
}
* 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.
--- /dev/null
+/*
+ * 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 <linux/config.h>
+#if defined(CONFIG_SYN_COOKIES)
+#include <linux/tcp.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <net/tcp.h>
+
+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
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);
{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}
};
*
* 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, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
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;
* 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);
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);
}
break;
case TCPOPT_SACK:
+ if (no_fancy)
+ break;
tp->sacks = (opsize-2)>>3;
if (tp->sacks<<3 == opsize-2) {
int i;
return 1;
}
}
- tcp_parse_options(th,tp);
+ tcp_parse_options(th,tp,0);
return 1;
}
* 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)
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);
/* 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
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;
* 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;
sk->shutdown = SHUTDOWN_MASK;
isn = tp->rcv_nxt + 128000;
+ if (isn == 0)
+ isn++;
sk = tp->af_specific->get_sock(skb, th);
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:
*
* 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
*
* 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 <linux/config.h>
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);
#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,
/* 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);
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;
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->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->dead)
+ goto dead;
+
+ 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();
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;
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;
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);
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;
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;
* 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 &&
* yet accepted()...
*/
sk = req->sk;
- break;
+ goto ende;
}
/* Check for syn retransmission */
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;
}
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:
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,
* 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
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;
+}
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $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
*
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:
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $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
* 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;
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...
*/
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;
}
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;
* 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),
}
newsk = sk_alloc(GFP_ATOMIC);
- if (newsk == NULL)
+ if (newsk == NULL) {
+ if (dst)
+ dst_release(dst);
return NULL;
+ }
memcpy(newsk, sk, sizeof(*newsk));
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);
}
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);
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,
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,
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;