]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.44pre3 2.1.44pre3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:25 +0000 (15:13 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:25 +0000 (15:13 -0500)
341 files changed:
Documentation/Configure.help
Documentation/ioctl-number.txt
Documentation/networking/README.cops [new file with mode: 0644]
Documentation/networking/net-modules.txt
MAINTAINERS
arch/i386/boot/compressed/Makefile
arch/i386/defconfig
arch/i386/kernel/entry.S
arch/i386/kernel/irq.c
arch/m68k/ifpsp060/iskeleton.S
arch/mips/Makefile
arch/mips/boot/Makefile
arch/mips/boot/mkboot.c [new file with mode: 0644]
arch/mips/config.in
arch/mips/dec/Makefile [new file with mode: 0644]
arch/mips/dec/boot.S [new file with mode: 0644]
arch/mips/dec/decstation.S [new file with mode: 0644]
arch/mips/dec/decstation.c [new file with mode: 0644]
arch/mips/dec/hw-access.c [new file with mode: 0644]
arch/mips/dec/int-handler.S [new file with mode: 0644]
arch/mips/dec/ld.script [new file with mode: 0644]
arch/mips/dec/reset.c [new file with mode: 0644]
arch/mips/dec/setup.c [new file with mode: 0644]
arch/mips/defconfig
arch/mips/deskstation/Makefile [new file with mode: 0644]
arch/mips/deskstation/hw-access.c [new file with mode: 0644]
arch/mips/deskstation/int-handler.S [new file with mode: 0644]
arch/mips/deskstation/io.c [new file with mode: 0644]
arch/mips/deskstation/reset.c [new file with mode: 0644]
arch/mips/deskstation/setup.c [new file with mode: 0644]
arch/mips/jazz/Makefile [new file with mode: 0644]
arch/mips/jazz/g364.c [new file with mode: 0644]
arch/mips/jazz/g364.fnt [new file with mode: 0644]
arch/mips/jazz/hw-access.c [new file with mode: 0644]
arch/mips/jazz/int-handler.S [new file with mode: 0644]
arch/mips/jazz/io.c [new file with mode: 0644]
arch/mips/jazz/jazzdma.c [new file with mode: 0644]
arch/mips/jazz/reset.c [new file with mode: 0644]
arch/mips/jazz/setup.c [new file with mode: 0644]
arch/mips/kernel/Makefile
arch/mips/kernel/bios32.c [deleted file]
arch/mips/kernel/branch.c [new file with mode: 0644]
arch/mips/kernel/entry.S
arch/mips/kernel/gdb-low.S
arch/mips/kernel/gdb-stub.c
arch/mips/kernel/head.S
arch/mips/kernel/init_task.c [new file with mode: 0644]
arch/mips/kernel/ioport.c
arch/mips/kernel/ipc.c
arch/mips/kernel/irix5sys.h [new file with mode: 0644]
arch/mips/kernel/irixelf.c [new file with mode: 0644]
arch/mips/kernel/irixioctl.c [new file with mode: 0644]
arch/mips/kernel/irixsig.c [new file with mode: 0644]
arch/mips/kernel/irq.c
arch/mips/kernel/jazz-c.c [deleted file]
arch/mips/kernel/jazzdma.c [deleted file]
arch/mips/kernel/magnum4000.S [deleted file]
arch/mips/kernel/mips_ksyms.c [new file with mode: 0644]
arch/mips/kernel/pci.c [new file with mode: 0644]
arch/mips/kernel/pica.S [deleted file]
arch/mips/kernel/proc.c [new file with mode: 0644]
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/r2300_fpu.S [new file with mode: 0644]
arch/mips/kernel/r2300_misc.S [new file with mode: 0644]
arch/mips/kernel/r2300_scall.S [new file with mode: 0644]
arch/mips/kernel/r2300_switch.S [new file with mode: 0644]
arch/mips/kernel/r4k_fpu.S [new file with mode: 0644]
arch/mips/kernel/r4k_misc.S [new file with mode: 0644]
arch/mips/kernel/r4k_scall.S [new file with mode: 0644]
arch/mips/kernel/r4k_switch.S [new file with mode: 0644]
arch/mips/kernel/r4xx0.S [deleted file]
arch/mips/kernel/r6000_fpu.S [new file with mode: 0644]
arch/mips/kernel/reset.c [new file with mode: 0644]
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/syscall.c
arch/mips/kernel/syscalls.h
arch/mips/kernel/sysirix.c [new file with mode: 0644]
arch/mips/kernel/sysmips.c
arch/mips/kernel/time.c
arch/mips/kernel/traps.c
arch/mips/kernel/tyne-c.c [deleted file]
arch/mips/kernel/tyne.S [deleted file]
arch/mips/kernel/unaligned.c [new file with mode: 0644]
arch/mips/kernel/vm86.c
arch/mips/ld.script [deleted file]
arch/mips/ld.script.big [new file with mode: 0644]
arch/mips/ld.script.little [new file with mode: 0644]
arch/mips/lib/Makefile
arch/mips/lib/checksum.c
arch/mips/lib/copy_user.S [new file with mode: 0644]
arch/mips/lib/csum.S [new file with mode: 0644]
arch/mips/lib/dump_tlb.c [new file with mode: 0644]
arch/mips/lib/io.c [new file with mode: 0644]
arch/mips/lib/memcpy.S [new file with mode: 0644]
arch/mips/lib/memset.c [new file with mode: 0644]
arch/mips/lib/pmaxcon.c [new file with mode: 0644]
arch/mips/lib/pmaxio.S [new file with mode: 0644]
arch/mips/lib/strlen_user.S [new file with mode: 0644]
arch/mips/lib/strncpy_user.S [new file with mode: 0644]
arch/mips/lib/tags.c [new file with mode: 0644]
arch/mips/lib/tinycon.c [new file with mode: 0644]
arch/mips/lib/watch.S [new file with mode: 0644]
arch/mips/mm/Makefile
arch/mips/mm/andes.c [new file with mode: 0644]
arch/mips/mm/extable.c [new file with mode: 0644]
arch/mips/mm/fault.c
arch/mips/mm/init.c
arch/mips/mm/loadmmu.c [new file with mode: 0644]
arch/mips/mm/r2300.c [new file with mode: 0644]
arch/mips/mm/r4xx0.c [new file with mode: 0644]
arch/mips/mm/r6000.c [new file with mode: 0644]
arch/mips/mm/tfp.c [new file with mode: 0644]
arch/mips/sgi/kernel/Makefile [new file with mode: 0644]
arch/mips/sgi/kernel/indyIRQ.S [new file with mode: 0644]
arch/mips/sgi/kernel/indy_hpc.c [new file with mode: 0644]
arch/mips/sgi/kernel/indy_int.c [new file with mode: 0644]
arch/mips/sgi/kernel/indy_mc.c [new file with mode: 0644]
arch/mips/sgi/kernel/indy_timer.c [new file with mode: 0644]
arch/mips/sgi/kernel/reset.c [new file with mode: 0644]
arch/mips/sgi/kernel/setup.c [new file with mode: 0644]
arch/mips/sgi/kernel/system.c [new file with mode: 0644]
arch/mips/sgi/kernel/time.c [new file with mode: 0644]
arch/mips/sgi/prom/Makefile [new file with mode: 0644]
arch/mips/sgi/prom/cmdline.c [new file with mode: 0644]
arch/mips/sgi/prom/console.c [new file with mode: 0644]
arch/mips/sgi/prom/env.c [new file with mode: 0644]
arch/mips/sgi/prom/file.c [new file with mode: 0644]
arch/mips/sgi/prom/init.c [new file with mode: 0644]
arch/mips/sgi/prom/memory.c [new file with mode: 0644]
arch/mips/sgi/prom/misc.c [new file with mode: 0644]
arch/mips/sgi/prom/printf.c [new file with mode: 0644]
arch/mips/sgi/prom/salone.c [new file with mode: 0644]
arch/mips/sgi/prom/tags.c [new file with mode: 0644]
arch/mips/sgi/prom/time.c [new file with mode: 0644]
arch/mips/sgi/prom/tree.c [new file with mode: 0644]
arch/mips/sni/Makefile [new file with mode: 0644]
arch/mips/sni/hw-access.c [new file with mode: 0644]
arch/mips/sni/int-handler.S [new file with mode: 0644]
arch/mips/sni/io.c [new file with mode: 0644]
arch/mips/sni/pci.c [new file with mode: 0644]
arch/mips/sni/reset.c [new file with mode: 0644]
arch/mips/sni/setup.c [new file with mode: 0644]
arch/mips/tools/Makefile [new file with mode: 0644]
arch/mips/tools/offset.c [new file with mode: 0644]
arch/sparc/config.in
arch/sparc/defconfig
arch/sparc64/config.in
arch/sparc64/defconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/binfmt_elf32.c
arch/sparc64/kernel/etrap.S
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/unaligned.c [new file with mode: 0644]
arch/sparc64/lib/blockops.S
arch/sparc64/lib/memcpy.S
arch/sparc64/lib/memset.S
arch/sparc64/mm/fault.c
arch/sparc64/mm/init.c
drivers/block/ide.c
drivers/char/ChangeLog
drivers/char/console.c
drivers/char/n_tty.c
drivers/char/random.c
drivers/char/serial.c
drivers/char/tty_io.c
drivers/isdn/sc/Makefile
drivers/net/Config.in
drivers/net/Makefile
drivers/net/Space.c
drivers/net/cops.c [new file with mode: 0644]
drivers/net/cops.h [new file with mode: 0644]
drivers/net/cops_ffdrv.h [new file with mode: 0644]
drivers/net/cops_ltdrv.h [new file with mode: 0644]
drivers/net/lapbether.c
drivers/net/sgiseeq.c [new file with mode: 0644]
drivers/net/sgiseeq.h [new file with mode: 0644]
drivers/net/sonic.c [new file with mode: 0644]
drivers/net/sonic.h [new file with mode: 0644]
drivers/sbus/char/bwtwo.c
drivers/sbus/char/cgfourteen.c
drivers/sbus/char/cgsix.c
drivers/sbus/char/cgthree.c
drivers/sbus/char/fb.h
drivers/sbus/char/leo.c
drivers/sbus/char/suncons.c
drivers/sbus/char/sunfb.c
drivers/sbus/char/tcx.c
drivers/sbus/char/weitek.c
fs/autofs/init.c
fs/buffer.c
fs/fat/misc.c
fs/ncpfs/inode.c
fs/nfs/inode.c
fs/proc/procfs_syms.c
fs/romfs/inode.c
fs/smbfs/inode.c
fs/super.c
include/asm-alpha/ioctls.h
include/asm-i386/ioctls.h
include/asm-i386/unistd.h
include/asm-m68k/ioctls.h
include/asm-mips/addrspace.h [new file with mode: 0644]
include/asm-mips/asm.h
include/asm-mips/asmmacro.h [new file with mode: 0644]
include/asm-mips/atomic.h [new file with mode: 0644]
include/asm-mips/bitops.h
include/asm-mips/bootinfo.h
include/asm-mips/branch.h [new file with mode: 0644]
include/asm-mips/bugs.h
include/asm-mips/byteorder.h
include/asm-mips/cache.h
include/asm-mips/cachectl.h
include/asm-mips/cacheops.h [new file with mode: 0644]
include/asm-mips/checksum.h
include/asm-mips/cpu.h [new file with mode: 0644]
include/asm-mips/current.h
include/asm-mips/decstation.h [new file with mode: 0644]
include/asm-mips/delay.h
include/asm-mips/deskstation.h [new file with mode: 0644]
include/asm-mips/dma.h
include/asm-mips/elf.h
include/asm-mips/errno.h
include/asm-mips/fcntl.h
include/asm-mips/floppy.h
include/asm-mips/hardirq.h [new file with mode: 0644]
include/asm-mips/ide.h [new file with mode: 0644]
include/asm-mips/init.h
include/asm-mips/inst.h [new file with mode: 0644]
include/asm-mips/io.h
include/asm-mips/ioctl.h
include/asm-mips/ioctls.h
include/asm-mips/ipc.h [new file with mode: 0644]
include/asm-mips/irq.h
include/asm-mips/jazz.h
include/asm-mips/jazzdma.h
include/asm-mips/keyboard.h
include/asm-mips/mc146818rtc.h
include/asm-mips/mipsconfig.h
include/asm-mips/mipsprom.h [new file with mode: 0644]
include/asm-mips/mipsregs.h
include/asm-mips/mman.h
include/asm-mips/mmu_context.h [new file with mode: 0644]
include/asm-mips/namei.h [new file with mode: 0644]
include/asm-mips/offset.h [new file with mode: 0644]
include/asm-mips/page.h
include/asm-mips/pci.h [new file with mode: 0644]
include/asm-mips/pgtable.h
include/asm-mips/poll.h [new file with mode: 0644]
include/asm-mips/posix_types.h [new file with mode: 0644]
include/asm-mips/processor.h
include/asm-mips/ptrace.h
include/asm-mips/r4kcache.h [new file with mode: 0644]
include/asm-mips/reboot.h [new file with mode: 0644]
include/asm-mips/reg.h
include/asm-mips/resource.h
include/asm-mips/scatterlist.h
include/asm-mips/segment.h
include/asm-mips/semaphore.h [new file with mode: 0644]
include/asm-mips/sgi.h [new file with mode: 0644]
include/asm-mips/sgialib.h [new file with mode: 0644]
include/asm-mips/sgiarcs.h [new file with mode: 0644]
include/asm-mips/sgidefs.h [new file with mode: 0644]
include/asm-mips/sgihpc.h [new file with mode: 0644]
include/asm-mips/sgimc.h [new file with mode: 0644]
include/asm-mips/sgint23.h [new file with mode: 0644]
include/asm-mips/shmparam.h
include/asm-mips/sigcontext.h
include/asm-mips/signal.h
include/asm-mips/slots.h [deleted file]
include/asm-mips/smp.h [new file with mode: 0644]
include/asm-mips/smp_lock.h [new file with mode: 0644]
include/asm-mips/sni.h [new file with mode: 0644]
include/asm-mips/socket.h
include/asm-mips/sockios.h [new file with mode: 0644]
include/asm-mips/softirq.h [new file with mode: 0644]
include/asm-mips/spinlock.h [new file with mode: 0644]
include/asm-mips/stackframe.h
include/asm-mips/stat.h
include/asm-mips/statfs.h
include/asm-mips/string.h
include/asm-mips/sysmips.h
include/asm-mips/system.h
include/asm-mips/termbits.h
include/asm-mips/termios.h
include/asm-mips/types.h
include/asm-mips/uaccess.h [new file with mode: 0644]
include/asm-mips/unaligned.h [new file with mode: 0644]
include/asm-mips/unistd.h
include/asm-mips/user.h
include/asm-mips/vector.h
include/asm-mips/watch.h [new file with mode: 0644]
include/asm-ppc/ioctls.h
include/asm-sparc/pgtable.h
include/asm-sparc64/asm_offsets.h
include/asm-sparc64/bitops.h
include/asm-sparc64/byteorder.h
include/asm-sparc64/elf.h
include/asm-sparc64/fbio.h
include/asm-sparc64/fs_mount.h [deleted file]
include/asm-sparc64/head.h
include/asm-sparc64/ioctls.h
include/asm-sparc64/mmu_context.h
include/asm-sparc64/page.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/processor.h
include/asm-sparc64/resource.h
include/asm-sparc64/sigcontext.h
include/asm-sparc64/system.h
include/asm-sparc64/uaccess.h
include/asm-sparc64/unistd.h
include/linux/fs.h
include/linux/if_arp.h
include/linux/net.h
include/linux/random.h
include/linux/sched.h
include/linux/slab.h
include/linux/sysctl.h
include/net/tcp.h
kernel/ksyms.c
kernel/sys.c
mm/slab.c
net/appletalk/ddp.c
net/ipv4/Config.in
net/ipv4/Makefile
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/syncookies.c [new file with mode: 0644]
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/utils.c
net/ipv6/icmp.c
net/ipv6/tcp_ipv6.c
net/unix/af_unix.c

index b7d55dd37191d36228689cba7bc7caa497cd628e..c3335af7eb4c6f4c3b16696e6702c061fc9a7815 100644 (file)
@@ -536,6 +536,19 @@ CONFIG_FIREWALL
   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
@@ -1326,7 +1339,7 @@ CONFIG_IPDDP
   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.
@@ -1338,6 +1351,26 @@ CONFIG_LTPC
   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
index 7d86d3168a01412d76bdaa07dc355c7edd35e08e..790bb18c7eb1de69a39a206d18ee7c4b14c2658a 100644 (file)
@@ -91,6 +91,7 @@ Code  Seq#    Include File            Comments
                                        <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!
diff --git a/Documentation/networking/README.cops b/Documentation/networking/README.cops
new file mode 100644 (file)
index 0000000..7956fd2
--- /dev/null
@@ -0,0 +1,39 @@
+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"
index bdf5a34a1d678df006f10e8c49cd88bb7c55944f..f0f3ab4700c2f388d6b9b3672ab328062c1aaadf 100644 (file)
@@ -159,6 +159,13 @@ atp.c: *Not modularized*
        (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
index 0c1384bc51951d188d15d79b33f54faad6e2712b..a6fd35086733dc3d72e46ebc4cca19ad4dd1e1d4 100644 (file)
@@ -260,6 +260,13 @@ M: layes@loran.com
 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
index 9a78bca69d5082751bf595ef1611407dea10b1db..653c12eba60d8980c1c0e1f9bd561552389fce23 100644 (file)
@@ -48,7 +48,7 @@ endif
 
 
 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; \
index ab30a25c81f3931802bf929408e5e482725fd911..fd248746dc548b8557a99f2ffed259121b39a764 100644 (file)
@@ -80,6 +80,7 @@ CONFIG_INET=y
 # 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)
index ac67da797b02e17fa4150c67aa1c5de7007d0873..e7b9e0779eafb3640b37bc11df0207a89c03de69 100644 (file)
@@ -526,6 +526,8 @@ ENTRY(sys_call_table)
        .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
index eedb1d0fe3c6d53cce6a401fa7fba5c363400d43..c6183993193d511bda4eaf06e886634b35936899 100644 (file)
@@ -82,12 +82,13 @@ static inline void mask_and_ack_irq(int irq_nr)
        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);
 }
 
index 3c310c2374b4961c2c184d563aa6cbab22143234..35542d4f11b1b7f4dfb6af7876206881d6db48e5 100644 (file)
 |
 
 #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        #
@@ -92,9 +75,8 @@ Lnotkern:
        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..
 
index e004c99a6dae636019edf04a2a93eab6f70b8f13..4266aa991ddb88d15f777a3c476cf1b9c5e70097 100644 (file)
@@ -1,4 +1,6 @@
 #
+# $Id: Makefile,v 1.5 1997/06/16 00:34:01 ralf Exp $
+#
 # arch/mips/Makefile
 #
 # This file is included by the global makefile so that you can add your own
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1994, 1995 by Ralf Baechle
+# Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+# DECStation modifications by Paul M. Antoine, 1996
 #
 
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-prefix         = mipsel-
-oformat                = a.out-mips-little-linux
+CROSS_COMPILE  = mipsel-
+ifdef CONFIG_MIPS_ECOFF
+oformat                = ecoff-littlemips
+else
+oformat                = a.out-mips-big-linux
+endif
+else
+CROSS_COMPILE  = mips-
+ifdef CONFIG_MIPS_ECOFF
+oformat                = ecoff-bigmips
 else
-prefix         = mips-
 oformat                = a.out-mips-big-linux
 endif
+endif
 
 ifdef CONFIG_EXTRA_ELF_COMPILER
-prefix         := $(prefix)linuxelf-
+CROSS_COMPILE  := $(CROSS_COMPILE)linuxelf-
 else
-prefix         := $(prefix)linux-
+CROSS_COMPILE  := $(CROSS_COMPILE)linux-
 endif
 
-AS             = $(prefix)as
-LD             = $(prefix)ld
-LINKFLAGS      = -N -Ttext 0x80000000
-#LINKFLAGS     = -oformat=$(oformat) -N -Ttext 0x80000000
-#HOSTCC                = gcc
-CC             = $(prefix)gcc -D__KERNEL__ -I$(TOPDIR)/include
-CPP            = $(CC) -E $(CFLAGS)
-AR             = $(prefix)ar
-RANLIB         = $(prefix)ranlib
-OBJCOPY                = $(prefix)objcopy
-OBJDUMP                = $(prefix)objdump
-STRIP          = $(prefix)strip
-NM             = $(prefix)nm
+LINKFLAGS      = -static -N
 
 #
 # The new ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
@@ -47,46 +46,134 @@ NM         = $(prefix)nm
 # old GCC these options are just the defaults.  At some point we might
 # make use of global pointer optimizations.
 #
+# The DECStation requires an ECOFF kernel for remote booting, other MIPS
+# machines may also.
+#
 ifdef CONFIG_ELF_KERNEL
-CFLAGS         := $(CFLAGS) -G0 -mno-abicalls -fno-pic
-LINKFLAGS      += -T arch/mips/ld.script
+CFLAGS         += -G 0 -mno-abicalls -fno-pic
+LINKFLAGS      += -G 0
+endif
+ifdef CONFIG_ECOFF_KERNEL
+CFLAGS         += -G 0 -mno-abicalls -fno-pic
+LINKFLAGS      += -G 0 -oformat ecoff-littlemips
 endif
 
 ifdef CONFIG_REMOTE_DEBUG
 CFLAGS         := $(CFLAGS) -g
 endif
 
+#
+# CPU dependand compiler/assembler options for optimization.
+#
 ifdef CONFIG_CPU_R3000
 CFLAGS         := $(CFLAGS) -mcpu=r3000 -mips1
-#ASFLAGS               := $(ASFLAGS) -mcpu=r3000 -mips1
 endif
 ifdef CONFIG_CPU_R6000
 CFLAGS         := $(CFLAGS) -mcpu=r6000 -mips2
-#ASFLAGS               := $(ASFLAGS) -mcpu=r6000 -mips2
+endif
+ifdef CONFIG_CPU_R4300
+CFLAGS         := $(CFLAGS) -mcpu=r4600 -Wa,-mcpu=vr4300 -mips2
 endif
 ifdef CONFIG_CPU_R4X00
-CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r4400 -mips2
-#ASFLAGS               := $(ASFLAGS) -mcpu=r4400 -mips2
+CFLAGS         := $(CFLAGS) -mcpu=r4600 -mips2
 endif
-ifdef CONFIG_CPU_R4600
-CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r4600 -mips2
-#ASFLAGS               := $(ASFLAGS) -mcpu=r4600 -mips2
+ifdef CONFIG_CPU_R5000
+CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2
 endif
 ifdef CONFIG_CPU_R8000
-CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
-#ASFLAGS               := $(ASFLAGS) -mcpu=r8000 -mips2
+CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2
 endif
 ifdef CONFIG_CPU_R10000
-CFLAGS         := $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
-#ASFLAGS               := $(ASFLAGS) -mcpu=r8000 -mips2
+CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2
+endif
+
+#
+# Board dependand options and extra files
+#
+ifdef CONFIG_ALGOR_P4032
+CORE_FILES    += arch/mips/algor/algor.o
+SUBDIRS       += arch/mips/algor
+#LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_ACER_PICA_61
+CORE_FILES    += arch/mips/jazz/jazz.o
+SUBDIRS       += arch/mips/jazz
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_DECSTATION
+CORE_FILES    += arch/mips/dec/dec.o
+SUBDIRS       += arch/mips/dec
+LINKSCRIPT    += arch/mips/dec/ld.script
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_DESKSTATION_RPC44
+CORE_FILES    += arch/mips/deskstation/deskstation.o
+SUBDIRS       += arch/mips/deskstation
+LOADADDR      += 0x80100000
 endif
+ifdef CONFIG_DESKSTATION_TYNE
+CORE_FILES    += arch/mips/deskstation/deskstation.o
+SUBDIRS       += arch/mips/deskstation
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_MIPS_MAGNUM_3000
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_MIPS_MAGNUM_4000
+CORE_FILES    += arch/mips/jazz/jazz.o
+SUBDIRS       += arch/mips/jazz
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_OLIVETTI_M700
+CORE_FILES    += arch/mips/jazz/jazz.o
+SUBDIRS       += arch/mips/jazz
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_SNI_RM200_PCI
+CORE_FILES    += arch/mips/sni/sni.o
+SUBDIRS       += arch/mips/sni
+LOADADDR      += 0x80000000
+endif
+ifdef CONFIG_SGI
+LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a
+SUBDIRS       += arch/mips/sgi/kernel arch/mips/sgi/prom
+#
+# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
+# 0x88002000 for production kernels.  Note that the value must be
+# 8kb aligned or the handling of the current variable will break.
+#
+LOADADDR      += 0x88002000
+HOSTCC        = cc
+endif
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+ifndef LINKSCRIPT
+ifndef CONFIG_CPU_LITTLE_ENDIAN
+LINKSCRIPT    = arch/mips/ld.script.big
+else
+LINKSCRIPT    = arch/mips/ld.script.little
+endif
+endif
+LINKFLAGS     += -T $(word 1,$(LINKSCRIPT))
 
-CFLAGS         := $(CFLAGS) -pipe
+ifdef LOADADDR
+LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+endif
+
+#
+# The pipe options is bad for my low-mem machine
+# Uncomment this if you want this.
+#
+CFLAGS         += -pipe
 
-HEAD := arch/mips/kernel/head.o
+HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
-SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib
-ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
+SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools)
+CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES)
 LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
@@ -102,6 +189,7 @@ zdisk: vmlinux
 archclean:
        @$(MAKEBOOT) clean
        $(MAKE) -C arch/$(ARCH)/kernel clean
+       $(MAKE) -C arch/$(ARCH)/tools clean
 
 archdep:
        @$(MAKEBOOT) dep
index 825837c979eaca64cf6048489c24999a625703ab..dd834efd95fcb1100f3954de0967f82761794ac7 100644 (file)
@@ -19,47 +19,32 @@ OBJS  = milo.o a.out.o
 # Drop some uninteresting sections in the kernel.
 # This is only relevant for ELF kernels but doesn't hurt a.out
 #
-DROP_SECTIONS  = .reginfo .mdebug
-
-#
-# The new options of binutils 2.6 help to shrink object files 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:
 
diff --git a/arch/mips/boot/mkboot.c b/arch/mips/boot/mkboot.c
new file mode 100644 (file)
index 0000000..35612d2
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * Make a bootable image from a Linux/MIPS kernel.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * This file is written in plain Kernighan & Ritchie C as it has to run
+ * on all crosscompile hosts no matter how braindead.  This code might
+ * also become part of Milo.  It's therefore important that we don't use
+ * seek because the Seek() call of the Magnum 4000 ARC BIOS is broken.
+ */
+#include <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;
+}
index f9f93afbcd743a28bd6d913b8f1433872775b25b..f9f93542f69857c7837467bf7bb88b926c33b56f 100644 (file)
 # see the Configure script.
 #
 mainmenu_name "Linux Kernel Configuration"
-  
+
 mainmenu_option next_comment
-comment 'Machine setup'
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
 
+mainmenu_option next_comment
+comment 'Machine selection'
 bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
-bool 'Support for DECstation' CONFIG_DECSTATION
-bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
-bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
-bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032
+  bool 'Support for DECstation' CONFIG_DECSTATION
+  bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
+  bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
+  bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
-bool 'Support for Olivetti M700' CONFIG_OLIVETTI_M700
-if [ "$CONFIG_ACER_PICA_61" = "y" -o \
-     "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
+bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
+if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
+       define_bool CONFIG_VIDEO_G364 y
+fi
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool 'Support for SGI workstations' CONFIG_SGI
+fi
+bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
+if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \
+     "$CONFIG_DESKSTATION_TYNE" = "y" ]; then
+       define_bool CONFIG_MIPS_ARC y
+fi
+if [ "$CONFIG_ACER_PICA_61" = "y" -o \
+     "$CONFIG_OLIVETTI_M700" = "y" -o \
+     "$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then
        define_bool CONFIG_MIPS_JAZZ y
 fi
+unset CONFIG_PCI
+if [ "$CONFIG_SNI_RM200_PCI" = "y" -o \
+     "$CONFIG_ALGOR_P4032" = "y" ]; then
+       define_bool CONFIG_PCI y
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'CPU selection'
 
 choice 'CPU type' \
        "R3000 CONFIG_CPU_R3000 \
         R6000 CONFIG_CPU_R6000 \
+        R4300 CONFIG_CPU_R4300 \
         R4x00 CONFIG_CPU_R4X00 \
-        R4600 CONFIG_CPU_R4600 \
+        R5000 CONFIG_CPU_R5000 \
         R8000 CONFIG_CPU_R8000 \
         R10000 CONFIG_CPU_R10000" R4x00
-if [ "$CONFIG_CPU_R3000" = "y" -o \
-     "$CONFIG_CPU_R6000" = "y" -o \
-     "$CONFIG_CPU_R4X00" = "y" -o \
-     "$CONFIG_CPU_R4600" = "y" -o \
-     "$CONFIG_CPU_R8000" = "y" ]; then
-       define_bool CONFIG_TLB_SHUTDOWN y
-fi
+endmenu
 
+mainmenu_option next_comment
+comment 'General setup'
+if [ "$CONFIG_DECSTATION" = "y" ]; then
+  bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL
+  define_bool CONFIG_CPU_LITTLE_ENDIAN y
+else
+  define_bool CONFIG_ELF_KERNEL y
+  bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
+fi
+if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then
+  define_bool CONFIG_BINFMT_IRIX y
+fi
 define_bool CONFIG_BINFMT_ELF y
-define_bool CONFIG_BINFMT_AOUT y
-bool 'Compile the kernel into the ELF object format' CONFIG_ELF_KERNEL
-if [ "$CONFIG_ELF_KERNEL" = "y" ]; then
-  bool 'Is your ELF compiler an extra compiler' CONFIG_EXTRA_ELF_COMPILER
+define_bool CONFIG_BINFMT_AOUT n
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
 fi
-bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
 bool 'Networking support' CONFIG_NET
-#bool 'PCI bios support' CONFIG_PCI
-#if [ "$CONFIG_PCI" = "y" ]; then
-#  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-#    bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
-#  fi
-#fi
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'Sysctl support' CONFIG_SYSCTL
+
+if [ "$CONFIG_SGI" != "y" ]; then
+  tristate 'Parallel port support' CONFIG_PNP_PARPORT
+fi
+
 endmenu
 
 mainmenu_option next_comment
 comment 'Loadable module support'
-bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-endmenu
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+  bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
+fi
 
-source drivers/block/Config.in
+#
+# All SGI block devices are SCSI based AFAIK. -davem
+#
+if [ "$CONFIG_SGI" != "y" ]; then
+  source drivers/block/Config.in
+fi
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
@@ -70,7 +110,27 @@ comment 'SCSI support'
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-  source drivers/scsi/Config.in
+       if [ "$CONFIG_SGI" = "y" ]; then
+               comment 'SCSI support type (disk, tape, CDrom)'
+
+               dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+               dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+               dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+               dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+
+               comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+
+               bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+
+               bool 'Verbose SCSI error reporting' CONFIG_SCSI_CONSTANTS
+
+               #mainmenu_option next_comment
+               comment 'SCSI low-level drivers'
+
+               dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI
+       else
+               source drivers/scsi/Config.in
+       fi
 fi
 endmenu
 
@@ -80,38 +140,76 @@ if [ "$CONFIG_NET" = "y" ]; then
 
   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
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
new file mode 100644 (file)
index 0000000..ccfba06
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: dec.o
+O_TARGET := dec.o
+O_OBJS  := boot.o int-handler.o decstation.o hw-access.o reset.o setup.o
+
+boot.o:        boot.S
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/dec/boot.S b/arch/mips/dec/boot.S
new file mode 100644 (file)
index 0000000..587c436
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * arch/mips/dec/boot.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because there is an
+ *      upgrade module for Personal DECStations with such a CPU!
+ */
+#include <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";
diff --git a/arch/mips/dec/decstation.S b/arch/mips/dec/decstation.S
new file mode 100644 (file)
index 0000000..a5a4f9b
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * arch/mips/kernel/decstation.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because I believe
+ *      that there is an upgrade module for Personal DECStations with
+ *      such CPU's!
+ *
+ * FIXME: still plenty to do in this file, as much of the code towards
+ *       the end hasn't been modified to suit the DECStation's interrupts.
+ *        (Paul, you need to fix this file to comply with NAPS.  Won't be
+ *         too hard - Ralf)
+ */
+#include <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
diff --git a/arch/mips/dec/decstation.c b/arch/mips/dec/decstation.c
new file mode 100644 (file)
index 0000000..ae64c32
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * arch/mips/dec/decstation.c
+ *
+ * Copyright (C) 1996 Paul M. Antoine
+ *
+ * Written by Paul Antoine.
+ *
+ * FIXME: still plenty to do in this file, as we don't yet fully fill
+ *        the boot info structure with DEC-specific tags.  Also still
+ *       too specific to the Person Decstattion 5000/2x!!
+ */
+
+#include <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 */
+
diff --git a/arch/mips/dec/hw-access.c b/arch/mips/dec/hw-access.c
new file mode 100644 (file)
index 0000000..31a8aab
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * DECstation specific hardware access code.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Paul Antoine
+ */
+#include <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
+};
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
new file mode 100644 (file)
index 0000000..9191574
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * arch/mips/dec/int-handler.S
+ *
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine.
+ *
+ * NOTE: There are references to R4X00 code in here, because there is an
+ *      upgrade module for Personal DECStations with such a CPU!
+ *
+ * FIXME: still plenty to do in this file, as much of the code hasn't been
+ *       modified to suit the DECStation's interrupts.
+ */
+#include <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
diff --git a/arch/mips/dec/ld.script b/arch/mips/dec/ld.script
new file mode 100644 (file)
index 0000000..f0cf33f
--- /dev/null
@@ -0,0 +1,47 @@
+OUTPUT_FORMAT("ecoff-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(dec_entry)
+SECTIONS
+{
+  /* This is probably a little simplistic, and is based on work by
+   * Chris Fraser of Softway Pty Ltd as used in his port of Vsta to
+   * the DECStation - Paul M. Antoine 21/1/96.
+   */
+  . = 0x80030000;
+  .text :
+  {
+    *(.text)
+    . = ALIGN(0x10);
+    _etext = .;
+    __etext = .;
+  }
+  .lit8 : {
+         *(.lit8)
+  }
+  .lit4 : {
+                 *(.lit4)
+  }
+  . = ALIGN(0x1000);
+  .data :
+  {
+    *(.data .rdata .rodata)
+    _edata  =  .;
+    __edata  =  .;
+  }
+  __bss_start = ALIGN(16) + 0x8000;
+  .sbss :
+  {
+    *(.sbss)
+    *(.scommon)
+  }
+  .bss :
+  {
+   *(.bss)
+   *(COMMON)
+   _end = ALIGN(4) ;
+   __end = ALIGN(4) ;
+  }
+  .reginfo : {
+    *(.reginfo)
+  }
+}
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
new file mode 100644 (file)
index 0000000..4d61d40
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  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);
+}
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
new file mode 100644 (file)
index 0000000..b748371
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#include <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;
+}
index e3ca88d1bc1b5c860fa9ef56cbf8b2518bb84051..33f54a301f992e4dda527bb4fd25c644ca23c869 100644 (file)
 #
 
 #
-# 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)
 #
@@ -53,30 +152,44 @@ CONFIG_BLK_DEV_FD=y
 #
 # Filesystems
 #
+# CONFIG_QUOTA is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
+# CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_UMSDOS_FS is not set
 CONFIG_PROC_FS=y
-# CONFIG_ISO9660_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_RNFS_BOOTP=y
+# CONFIG_RNFS_RARP is not set
+CONFIG_NFSD=y
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+CONFIG_ISO9660_FS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_SMB_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
 
 #
-# character devices
+# Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_CYCLADES is not set
-# CONFIG_STALDRV is not set
-# CONFIG_PRINTER is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_PSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-# CONFIG_ATIXL_BUSMOUSE is not set
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_MOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_FTAPE is not set
 # CONFIG_APM is not set
-# CONFIG_SERIAL is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
 
 #
 # Sound
@@ -86,4 +199,5 @@ CONFIG_VT_CONSOLE=y
 #
 # Kernel hacking
 #
+# CONFIG_REMOTE_DEBUG is not set
 # CONFIG_PROFILE is not set
diff --git a/arch/mips/deskstation/Makefile b/arch/mips/deskstation/Makefile
new file mode 100644 (file)
index 0000000..903a73e
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# Makefile for the Deskstation family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: deskstation.o
+O_TARGET := deskstation.o
+O_OBJS  := hw-access.o int-handler.o reset.o setup.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/deskstation/hw-access.c b/arch/mips/deskstation/hw-access.c
new file mode 100644 (file)
index 0000000..418bac5
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Low-level hardware access stuff for Deskstation rPC44/Tyne
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#include <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
diff --git a/arch/mips/deskstation/int-handler.S b/arch/mips/deskstation/int-handler.S
new file mode 100644 (file)
index 0000000..b7fd32d
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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)
diff --git a/arch/mips/deskstation/io.c b/arch/mips/deskstation/io.c
new file mode 100644 (file)
index 0000000..cd33e2e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Low level I/O functions for Jazz family machine.
+ *
+ * FIXME: This implementation fits the Tyne.  How does the EISA rPC44 handle
+ * the eight high address bits?
+ */
+#include <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);
+}
diff --git a/arch/mips/deskstation/reset.c b/arch/mips/deskstation/reset.c
new file mode 100644 (file)
index 0000000..9d45898
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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);
+}
diff --git a/arch/mips/deskstation/setup.c b/arch/mips/deskstation/setup.c
new file mode 100644 (file)
index 0000000..8b70a65
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <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");
+}
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
new file mode 100644 (file)
index 0000000..3868b60
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Makefile for the Jazz family specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: jazz.o
+O_TARGET := jazz.o
+O_OBJS  := hw-access.o int-handler.o jazzdma.o reset.o setup.o
+
+ifdef CONFIG_VIDEO_G364
+O_OBJS += g364.o
+endif
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/jazz/g364.c b/arch/mips/jazz/g364.c
new file mode 100644 (file)
index 0000000..92e1305
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ *  linux/drivers/char/g364.c
+ *
+ *  Copyright (C) 1996  Wayne Hodgen
+ *
+ *  Based on and using chunks of Jay Estabrooks tga.c
+ *
+ * This module exports the console io support for Inmos's G364 controller
+ * used in Mips Magnums and clones. Based on the hardware desc for the
+ * Olivetti M700-10 ie. an Inmos G364 based card in a dedicated video slot,
+ * 2MB dual ported VRAM with a 64 bit data path, 256 color lookup table,
+ * palette of 16.7M and a user definable 64x64 hardware cursor.
+ */
+#include <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)
+{
+}
diff --git a/arch/mips/jazz/g364.fnt b/arch/mips/jazz/g364.fnt
new file mode 100644 (file)
index 0000000..fd4890f
--- /dev/null
@@ -0,0 +1,4097 @@
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x07,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x07,0x07,0x07,0x07,0x00,0x07,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x07,
+0x07,0x00,0x07,0x00,0x00,0x07,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x07,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,
+0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,
+0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x07,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00,
+0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+0x07,0x07,0x07,0x00,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,
+0x07,0x07,0x00,0x07,0x00,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x07,0x07,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x07,0x07,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x00,
+0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x07,0x07,0x07,0x07,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x07,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,
+0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,
+0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0
diff --git a/arch/mips/jazz/hw-access.c b/arch/mips/jazz/hw-access.c
new file mode 100644 (file)
index 0000000..52a6116
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Low-level hardware access stuff for Jazz family machines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ */
+#include <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
+};
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
new file mode 100644 (file)
index 0000000..87fd335
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * arch/mips/jazz/pica.S
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Jazz family specific stuff
+ *
+ * To do: On Jazz machines we remap some non-ISA interrupts to ISA
+ *        interrupts.  These interrupts should use their own vectors.
+ *        Squeeze the last cycles out of the handlers.  Only a dead
+ *        cycle is a good cycle.
+ */
+#include <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
diff --git a/arch/mips/jazz/io.c b/arch/mips/jazz/io.c
new file mode 100644 (file)
index 0000000..a151b99
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Low level I/O functions for Jazz family machines.
+ *
+ * Copyright (C) 1997 by Ralf Baechle.
+ */
+#include <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;
+       }
+}
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
new file mode 100644 (file)
index 0000000..4701852
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * arch/mips/jazz/jazzdma.c
+ *
+ * Mips Jazz DMA controller support
+ * Copyright (C) 1995, 1996 by Andreas Busse
+ *
+ * NOTE: Some of the argument checking could be removed when
+ * things have settled down. Also, instead of returning 0xffffffff
+ * on failure of vdma_alloc() one could leave page #0 unused
+ * and return the more usual NULL pointer as logical address.
+ */
+#include <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;
+}
diff --git a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c
new file mode 100644 (file)
index 0000000..ccc7a7c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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 */
+}
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
new file mode 100644 (file)
index 0000000..805efa8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <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;
+}
index 32d2a80414a6ca221ceb88c5c2618af5dfe89ca0..21dd3610bb4e94a36f37746c5fbc7faad00d4105 100644 (file)
@@ -6,72 +6,44 @@
 # unless it's something special (ie not a .c file).
 #
 
-.S.s:
-       $(CPP) $(CFLAGS) $< -o $*.s
 .S.o:
        $(CC) $(CFLAGS) -c $< -o $*.o
 
-all:   kernel.o head.o
+all:   kernel.o head.o init_task.o
 EXTRA_ASFLAGS = -mips3 -mcpu=r4000
 O_TARGET := kernel.o
-O_OBJS := process.o signal.o entry.o traps.o irq.o ptrace.o vm86.o ioport.o \
-       setup.o syscall.o sysmips.o time.o bios32.o ipc.o
+O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
+          ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \
+          r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \
+          r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o
+OX_OBJS := mips_ksyms.o
 
 #
-# Kernel debugging
+# SGI's have very different interrupt/timer hardware.
 #
-ifdef CONFIG_REMOTE_DEBUG
-OBJS += gdb-low.o gdb-stub.o 
+ifndef CONFIG_SGI
+O_OBJS += irq.o time.o
 endif
 
 #
-# Board specific code
+# Do we want to be able to execute IRIX elf binaries?
 #
-ifdef CONFIG_MIPS_JAZZ
-O_OBJS += jazzdma.o jazz-c.o
-endif
-
-ifdef CONFIG_ACER_PICA_61
-O_OBJS += pica.o
-endif
-
-ifdef CONFIG_DESKSTATION_TYNE
-O_OBJS += tyne.o tyne-c.o
-endif
-
-ifdef CONFIG_MIPS_MAGNUM_4000
-O_OBJS += magnum4000.o
+ifdef CONFIG_BINFMT_IRIX
+O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o
 endif
 
 #
-# CPU model specific code
+# Kernel debugging
 #
-ifdef CONFIG_CPU_R2000
-O_OBJS += r3000.o
-endif
-
-ifdef CONFIG_CPU_R3000
-O_OBJS += r3000.o
-endif
-
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R4600
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R6000
-       exit 1                  # no detailed information about CPU yet.
-endif
-
-ifdef CONFIG_CPU_R8000
-       exit 1                  # no detailed information about CPU yet.
+ifdef CONFIG_REMOTE_DEBUG
+O_OBJS += gdb-low.o gdb-stub.o 
 endif
 
-ifdef CONFIG_CPU_R10000
-O_OBJS += r4xx0.o
+#
+# Depending from some other kernel option
+#
+ifdef CONFIG_PROC_FS
+O_OBJS += proc.o
 endif
 
 #
@@ -88,13 +60,23 @@ entry.o: entry.S
 
 head.o: head.S
 
-magnum4000.o: magnum4000.S
-
-pica.o: pica.S
-
-r4xx0.o: r4xx0.S
-
-tyne.o: tyne.S
+#r4k_switch.o: r4k_switch.S
+#
+#r4k_misc.o: r4k_misc.S
+#
+#r4k_scall.o: r4k_scall.S
+#
+#r4k_fpu.o: r4k_fpu.S
+#
+#r2300_switch.o: r2300_switch.S
+#
+#r2300_misc.o: r2300_misc.S
+#
+#r2300_scall.o: r2300_scall.S
+#
+#r2300_fpu.o: r2300_fpu.S
+#
+#r6000_fpu.o: r6000_fpu.S
 
 clean:
 
diff --git a/arch/mips/kernel/bios32.c b/arch/mips/kernel/bios32.c
deleted file mode 100644 (file)
index 1fe61fa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * bios 32 replacement
- */
-unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
-{
-       return memory_start;
-}
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
new file mode 100644 (file)
index 0000000..b9d138a
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Branch and jump emulation.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <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;
+}
index c1b2160aad709001938970a1a0a174c00986ba25..682e00cda464efd0c9fa2d735d06b50da3361b91 100644 (file)
  * 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
@@ -120,145 +98,126 @@ EXPORT(return)   RESTORE_ALL
                .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.
@@ -281,31 +240,43 @@ EXPORT(IRQ_vectors)
                .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"
index ea775e7329ef211dc58aad65352e53c45d03f13e..6657bd77ce7428019fc8e88dc66eff9cf3e0e8c3 100644 (file)
@@ -9,9 +9,9 @@
 #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>
 
@@ -33,7 +33,8 @@
                 */
                lui     k1,%hi(kernelsp)
                lw      k1,%lo(kernelsp)(k1)
-1:             move    k0,sp
+1:
+               move    k0,sp
                subu    sp,k1,GDB_FR_SIZE
                sw      k0,GDB_FR_REG29(sp)
                sw      v0,GDB_FR_REG2(sp)
                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)
index e1544bc89a1592785cb0c7b1da1e733e3871a8cc..255ec222863585b1985d9a51f17bbd9ef5a1da1f 100644 (file)
@@ -70,7 +70,6 @@
 
 #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>
@@ -326,7 +325,10 @@ static struct hard_trap_info
 void set_debug_traps(void)
 {
        struct hard_trap_info *ht;
+       unsigned long flags;
+       unsigned char c;
 
+       save_flags(flags); cli();
        for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
                set_except_vector(ht->tt, trap_low);
   
@@ -334,9 +336,14 @@ void set_debug_traps(void)
         * In case GDB is started before us, ack any packets
         * (presumably "$?#xx") sitting there.
         */
+       while((c = getDebugChar()) != '$');
+       while((c = getDebugChar()) != '#');
+       c = getDebugChar(); /* eat first csum byte */
+       c = getDebugChar(); /* eat second csum byte */
+       putDebugChar('+'); /* ack it */
 
-       putDebugChar ('+');
        initialized = 1;
+       restore_flags(flags);
 
        breakpoint();
 }
@@ -605,7 +612,7 @@ void handle_exception (struct gdb_regs *regs)
                         * NB: We flush both caches, just to be sure...
                         */
 
-                       sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE);
+                       flush_cache_all();
                        return;
                        /* NOTREACHED */
                        break;
index a43761a27e385cc90205e870966b666b4c0486f5..27c700a95c2a0c200e487cde5d9f84077596f750 100644 (file)
 /*
  *  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.
  */
 
 /*
@@ -282,19 +645,25 @@ map0table:        PTR     map0_dummy              # machtype = unknown
                PTR     map0_tyne               # Deskstation Tyne
                PTR     map0_pica61             # Acer Pica-61
                PTR     map0_magnum4000         # MIPS Magnum 4000PC (RC4030)
+               PTR     map0_dummy
+               PTR     map0_dummy              # DEC Personal DECStation 5000/2x (for now)
+               PTR     map0_sni_rm200_pci      # SNI RM200 PCI
+               PTR     map0_dummy              # SGI INDY
 
 map0_dummy:    .word   0                       # 0 entries
 
                .align  3
 /*
- * Initial mappings for Deskstation rPC boards.
- * RB: Untested goodie - I don't have such a board.
+ * Deskstation rpc44 mappings.  This machine has its EISA bus at physical
+ * address 0xa0000000 which we map for 32M, but that doesn't match EISA
+ * spec.  Not sure what to do about this.  Its I/O ports are memory mapped
+ * at physical memory location 0xb0000000.
  */
 map0_rpc:      .word   2                       # no. of wired TLB entries
                .word   0                       # pad for alignment
 
-MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)     # VESA DMA cache
-MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)    # VESA I/O and memory space
+MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M)    # ISA Memory space
+MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K)    # ISA I/O Space
 
 /*
  * Initial mappings for Deskstation Tyne boards.
@@ -330,51 +699,52 @@ MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)        # PCR (???)
  * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
  * FIXME: Remove or merge some of the mappings.
  */
-
 map0_magnum4000:
                .word   8                       # no. wired TLB entries
                .word   0                       # dummy
 
-MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, 0x7e000)   # 0
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, 0x1e000)   # 1 local I/O
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, 0)         # 2 IRQ source
-MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, 0x1fe000)  # 3 local video ctrl
-MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, 0x1fe000)  # 4 ext. video ctrl
-MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, 0x7fe000)  # 5 local video mem.
-MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, 0x1ffe000) # 6 ISA I/O and mem.
-MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, 0)         # 7 PCR
+MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K)   # 0
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)    # 1 local I/O
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)     # 2 IRQ source
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)     # 3 local video ctrl
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)     # 4 ext. video ctrl
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)     # 5 local video mem.
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)    # 6 ISA I/O and mem.
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)     # 7 PCR
 
+/*
+ * The RM200 doesn't need any wired entries.
+ */
+map0_sni_rm200_pci:
+               .word   0                       # no. wired TLB entries
+               .word   0                       # dummy
 
                        .text
 
                        .org    0x1000
-                       .globl  swapper_pg_dir
-swapper_pg_dir         =       . + (KSEG1-KSEG0)
+                       EXPORT(swapper_pg_dir)
 
-/*
- * The page tables are initialized to only 4MB here - the final page
- * tables are set up later depending on memory size.
- */
                        .org    0x2000
-                       EXPORT(pg0)
-
-                       .org    0x3000
                        EXPORT(empty_bad_page)
 
-                       .org    0x4000
+                       .org    0x3000
                        EXPORT(empty_bad_page_table)
 
-                       .org    0x5000
+                       .org    0x4000
                        EXPORT(empty_zero_page)
 
-                       .org    0x6000
+                       .org    0x5000
                        EXPORT(invalid_pte_table)
 
-                       .org    0x7000
+                       .org    0x6000
 
+                       /*
+                        * init_task_union follows here in the .text segment.
+                        * Keep this aligned to a 8kb boundary!
+                        */
+                       .data
                        EXPORT(cache_error_buffer)
                        .fill   32*4,1,0
 
-                       .data
                        EXPORT(kernelsp)
                        PTR     0
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c
new file mode 100644 (file)
index 0000000..cc0a192
--- /dev/null
@@ -0,0 +1,22 @@
+#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 };
index ff6c0d518f35cfd6b1515566757ae1508877ea20..cc05810380546d261696b8001ca5d4b7e0d417cc 100644 (file)
@@ -15,8 +15,6 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
        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
index 668deb8e1739a4189dc957d58e8ab642da46b08b..2e91b675585336e02f677ddf4638afedbcd55d00 100644 (file)
@@ -2,11 +2,9 @@
  * linux/arch/mips/kernel/ipc.c
  *
  * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/i386
+ * have a non-standard calling sequence on the Linux/MIPS
  * platform.
  */
-
-#include <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();
@@ -46,9 +43,9 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
                        ret = -EINVAL;
                        if (!ptr)
                                goto out;
-                       if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
-                               goto out;
-                       fourth.__pad = (void *) get_fs_long(ptr);
+                       ret = -EFAULT;
+                       if (get_user(fourth.__pad, (void **) ptr))
+                               goto out;       
                        ret = sys_semctl (first, second, third, fourth);
                        goto out;
                        }
@@ -66,12 +63,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
                        switch (version) {
                        case 0: {
                                struct ipc_kludge tmp;
+                               ret = -EINVAL;
                                if (!ptr)
-                                       return -EINVAL;
-                               if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
                                        goto out;
-                               memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
-                                              sizeof (tmp));
+                               ret = -EFAULT;
+                               if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, 
+                                                                  sizeof (tmp)))
+                                       goto out;       
                                ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
                                goto out;
                                }
@@ -95,15 +93,12 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
                        switch (version) {
                        case 0: default: {
                                ulong raddr;
-                               if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
-                                       goto out;
                                ret = sys_shmat (first, (char *) ptr, second, &raddr);
                                if (ret)
                                        goto out;
-                               put_fs_long (raddr, (ulong *) third);
-                               ret = 0;
+                               ret = put_user (raddr, (ulong *) third);
                                goto out;
-                               }
+                       }
                        case 1: /* iBCS2 emulator entry point */
                                ret = -EINVAL;
                                if (get_fs() != get_ds())
@@ -129,7 +124,4 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
 out:
        unlock_kernel();
        return ret;
-#else /* CONFIG_SYSVIPC */
-       return -ENOSYS;
-#endif /* CONFIG_SYSVIPC */
 }
diff --git a/arch/mips/kernel/irix5sys.h b/arch/mips/kernel/irix5sys.h
new file mode 100644 (file)
index 0000000..7c49b19
--- /dev/null
@@ -0,0 +1,1024 @@
+/* $Id: irix5sys.h,v 1.1 1997/06/06 09:32:29 ralf Exp $
+ * irix5sys.h: 32-bit IRIX5 ABI system call table.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+/* This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts.  Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ */
+
+/* Keys:
+ *         V == Valid and should work as expected for most cases.
+ *        HV == Half Valid, some things will work, some likely will not
+ *        IV == InValid, certainly will not work at all yet
+ *        ?V == ?'ably Valid, I have not done enough looking into it
+ *        DC == Don't Care, a rats ass we couldn't give
+ */
+
+SYS(sys_syscall, 0)                    /* 1000  sysindir()            V*/
+SYS(sys_exit, 1)                       /* 1001  exit()                V*/
+SYS(sys_fork, 0)                       /* 1002  fork()                V*/
+SYS(sys_read, 3)                       /* 1003  read()                V*/
+SYS(sys_write, 3)                      /* 1004  write()               V*/
+SYS(sys_open, 3)                       /* 1005  open()                V*/
+SYS(sys_close, 1)                      /* 1006  close()               V*/
+SYS(irix_unimp, 0)                     /* 1007  (XXX IRIX 4 wait)     V*/
+SYS(sys_creat, 2)                      /* 1008  creat()               V*/
+SYS(sys_link, 2)                       /* 1009  link()                V*/
+SYS(sys_unlink, 1)                     /* 1010  unlink()              V*/
+SYS(irix_exec, 0)                      /* 1011  exec()                V*/
+SYS(sys_chdir, 1)                      /* 1012  chdir()               V*/
+SYS(irix_gtime, 0)                     /* 1013  time()                V*/
+SYS(irix_unimp, 0)                     /* 1014  (XXX IRIX 4 mknod)    V*/
+SYS(sys_chmod, 2)                      /* 1015  chmod()               V*/
+SYS(irix_chown, 3)                     /* 1016  chown()               V*/
+SYS(irix_brk, 1)                       /* 1017  break()               V*/
+SYS(irix_unimp, 0)                     /* 1018  (XXX IRIX 4 stat)     V*/
+SYS(sys_lseek, 3)                      /* 1019  lseek()     XXX64bit HV*/
+SYS(irix_getpid, 0)                    /* 1020  getpid()              V*/
+SYS(irix_mount, 6)                     /* 1021  mount()              IV*/
+SYS(sys_umount, 1)                     /* 1022  umount()              V*/
+SYS(sys_setuid, 1)                     /* 1023  setuid()              V*/
+SYS(irix_getuid, 0)                    /* 1024  getuid()              V*/
+SYS(irix_stime, 1)                     /* 1025  stime()               V*/
+SYS(irix_unimp, 4)                     /* 1026  XXX ptrace()         IV*/
+SYS(irix_alarm, 1)                     /* 1027  alarm()               V*/
+SYS(irix_unimp, 0)                     /* 1028  (XXX IRIX 4 fstat)    V*/
+SYS(irix_pause, 0)                     /* 1029  pause()               V*/
+SYS(sys_utime, 2)                      /* 1030  utime()               V*/
+SYS(irix_unimp, 0)                     /* 1031  nuthin'               V*/
+SYS(irix_unimp, 0)                     /* 1032  nobody home man...    V*/
+SYS(sys_access, 2)                     /* 1033  access()              V*/
+SYS(sys_nice, 1)                       /* 1034  nice()                V*/
+SYS(irix_statfs, 2)                    /* 1035  statfs()              V*/
+SYS(sys_sync, 0)                       /* 1036  sync()                V*/
+SYS(sys_kill, 2)                       /* 1037  kill()                V*/
+SYS(irix_fstatfs, 2)                   /* 1038  fstatfs()             V*/
+SYS(irix_setpgrp, 1)                   /* 1039  setpgrp()             V*/
+SYS(irix_syssgi, 0)                    /* 1040  syssgi()             HV*/
+SYS(sys_dup, 1)                                /* 1041  dup()                 V*/
+SYS(sys_pipe, 0)                       /* 1042  pipe()                V*/
+SYS(irix_times, 1)                     /* 1043  times()               V*/
+SYS(irix_unimp, 0)                     /* 1044  XXX profil()         IV*/
+SYS(irix_unimp, 0)                     /* 1045  XXX lock()           IV*/
+SYS(sys_setgid, 1)                     /* 1046  setgid()              V*/
+SYS(irix_getgid, 0)                    /* 1047  getgid()              V*/
+SYS(irix_unimp, 0)                     /* 1048  (XXX IRIX 4 ssig)     V*/
+SYS(irix_msgsys, 6)                    /* 1049  sys_msgsys            V*/
+SYS(sys_sysmips, 4)                    /* 1050  sysmips()            HV*/
+SYS(irix_unimp, 0)                     /* 1051  XXX sysacct()        IV*/
+SYS(irix_shmsys, 5)                    /* 1052  sys_shmsys            V*/
+SYS(irix_semsys, 0)                    /* 1053  sys_semsys            V*/
+SYS(irix_ioctl, 3)                     /* 1054  ioctl()              HV*/
+SYS(irix_uadmin, 0)                    /* 1055  XXX sys_uadmin()     HC*/
+SYS(irix_sysmp, 0)                     /* 1056  sysmp()              HV*/
+SYS(irix_utssys, 4)                    /* 1057  sys_utssys()         HV*/
+SYS(irix_unimp, 0)                     /* 1058  nada enchilada        V*/
+SYS(irix_exece, 0)                     /* 1059  exece()               V*/
+SYS(sys_umask, 1)                      /* 1060  umask()               V*/
+SYS(sys_chroot, 1)                     /* 1061  chroot()              V*/
+SYS(irix_fcntl, 3)                     /* 1062  fcntl()              ?V*/
+SYS(irix_ulimit, 2)                    /* 1063  ulimit()             HV*/
+SYS(irix_unimp, 0)                     /* 1064  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1065  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1066  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1067  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1068  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1069  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1070  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1071  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1072  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1073  XXX AFS shit         DC*/
+SYS(irix_unimp, 0)                     /* 1074  nuttin'               V*/
+SYS(irix_unimp, 0)                     /* 1075  XXX sys_getrlimit64()IV*/
+SYS(irix_unimp, 0)                     /* 1076  XXX sys_setrlimit64()IV*/
+SYS(sys_nanosleep, 2)                  /* 1077  nanosleep()           V*/
+SYS(irix_lseek64, 5)                   /* 1078  lseek64()            ?V*/
+SYS(sys_rmdir, 1)                      /* 1079  rmdir()               V*/
+SYS(sys_mkdir, 2)                      /* 1080  mkdir()               V*/
+SYS(sys_getdents, 3)                   /* 1081  getdents()            V*/
+SYS(irix_sginap, 1)                    /* 1082  sys_sginap()          V*/
+SYS(irix_sgikopt, 3)                   /* 1083  sys_sgikopt()        DC*/
+SYS(sys_sysfs, 3)                      /* 1084  sysfs()              ?V*/
+SYS(irix_unimp, 0)                     /* 1085  XXX sys_getmsg()     DC*/
+SYS(irix_unimp, 0)                     /* 1086  XXX sys_putmsg()     DC*/
+SYS(sys_poll, 3)                       /* 1087  poll()                V*/
+SYS(irix_sigreturn, 0)                 /* 1088  sigreturn()          ?V*/
+SYS(sys_accept, 3)                     /* 1089  accept()              V*/
+SYS(sys_bind, 3)                       /* 1090  bind()                V*/
+SYS(sys_connect, 3)                    /* 1091  connect()             V*/
+SYS(irix_gethostid, 0)                 /* 1092  sys_gethostid()      ?V*/
+SYS(sys_getpeername, 3)                        /* 1093  getpeername()         V*/
+SYS(sys_getsockname, 3)                        /* 1094  getsockname()         V*/
+SYS(sys_getsockopt, 5)                 /* 1095  getsockopt()          V*/
+SYS(sys_listen, 2)                     /* 1096  listen()              V*/
+SYS(sys_recv, 4)                       /* 1097  recv()                V*/
+SYS(sys_recvfrom, 6)                   /* 1098  recvfrom()            V*/
+SYS(sys_recvmsg, 3)                    /* 1099  recvmsg()             V*/
+SYS(sys_select, 5)                     /* 1100  select()              V*/
+SYS(sys_send, 4)                       /* 1101  send()                V*/
+SYS(sys_sendmsg, 3)                    /* 1102  sendmsg()             V*/
+SYS(sys_sendto, 6)                     /* 1103  sendto()              V*/
+SYS(irix_sethostid, 1)                 /* 1104  sys_sethostid()      ?V*/
+SYS(sys_setsockopt, 5)                 /* 1105  setsockopt()          V*/
+SYS(sys_shutdown, 2)                   /* 1106  shutdown()           ?V*/
+SYS(irix_socket, 3)                    /* 1107  socket()              V*/
+SYS(sys_gethostname, 2)                        /* 1108  sys_gethostname()    ?V*/
+SYS(sys_sethostname, 2)                        /* 1109  sethostname()        ?V*/
+SYS(irix_getdomainname, 2)             /* 1110  sys_getdomainname()  ?V*/
+SYS(sys_setdomainname, 2)              /* 1111  setdomainname()      ?V*/
+SYS(sys_truncate, 2)                   /* 1112  truncate()            V*/
+SYS(sys_ftruncate, 2)                  /* 1113  ftruncate()           V*/
+SYS(sys_rename, 2)                     /* 1114  rename()              V*/
+SYS(sys_symlink, 2)                    /* 1115  symlink()             V*/
+SYS(sys_readlink, 3)                   /* 1116  readlink()            V*/
+SYS(irix_unimp, 0)                     /* 1117  XXX IRIX 4 lstat()   DC*/
+SYS(irix_unimp, 0)                     /* 1118  nothin'               V*/
+SYS(irix_unimp, 0)                     /* 1119  XXX nfs_svc()        DC*/
+SYS(irix_unimp, 0)                     /* 1120  XXX nfs_getfh()      DC*/
+SYS(irix_unimp, 0)                     /* 1121  XXX async_daemon()   DC*/
+SYS(irix_unimp, 0)                     /* 1122  XXX exportfs()       DC*/
+SYS(sys_setregid, 2)                   /* 1123  setregid()            V*/
+SYS(sys_setreuid, 2)                   /* 1124  setreuid()            V*/
+SYS(sys_getitimer, 2)                  /* 1125  getitimer()           V*/
+SYS(sys_setitimer, 3)                  /* 1126  setitimer()           V*/
+SYS(irix_unimp, 1)                     /* 1127  XXX adjtime()        IV*/
+SYS(irix_gettimeofday, 1)              /* 1128  gettimeofday()        V*/
+SYS(irix_unimp, 0)                     /* 1129  XXX sproc()          IV*/
+SYS(irix_prctl, 0)                     /* 1130  prctl()              HV*/
+SYS(irix_unimp, 0)                     /* 1131  XXX procblk()        IV*/
+SYS(irix_unimp, 0)                     /* 1132  XXX sprocsp()        IV*/
+SYS(irix_unimp, 0)                     /* 1133  XXX sgigsc()         IV*/
+SYS(irix_mmap32, 6)                    /* 1134  mmap()    XXXflags?  ?V*/
+SYS(sys_munmap, 2)                     /* 1135  munmap()              V*/
+SYS(sys_mprotect, 3)                   /* 1136  mprotect()            V*/
+SYS(sys_msync, 4)                      /* 1137  msync()               V*/
+SYS(irix_madvise, 3)                   /* 1138  madvise()            DC*/
+SYS(irix_pagelock, 3)                  /* 1139  pagelock()           IV*/
+SYS(irix_getpagesize, 0)               /* 1140  getpagesize()         V*/
+SYS(irix_quotactl, 0)                  /* 1141  quotactl()            V*/
+SYS(irix_unimp, 0)                     /* 1142  nobody home man       V*/
+SYS(sys_getpgid, 1)                    /* 1143  BSD getpgrp()         V*/
+SYS(irix_BSDsetpgrp, 2)                        /* 1143  BSD setpgrp()         V*/
+SYS(sys_vhangup, 0)                    /* 1144  vhangup()             V*/
+SYS(sys_fsync, 1)                      /* 1145  fsync()               V*/
+SYS(sys_fchdir, 1)                     /* 1146  fchdir()              V*/
+SYS(sys_getrlimit, 2)                  /* 1147  getrlimit()          ?V*/
+SYS(sys_setrlimit, 2)                  /* 1148  setrlimit()          ?V*/
+SYS(sys_cacheflush, 3)                 /* 1150  cacheflush()         HV*/
+SYS(sys_cachectl, 3)                   /* 1151  cachectl()           HV*/
+SYS(sys_fchown, 3)                     /* 1152  fchown()             ?V*/
+SYS(sys_fchmod, 2)                     /* 1153  fchmod()             ?V*/
+SYS(irix_unimp, 0)                     /* 1154  XXX IRIX 4 wait3()    V*/
+SYS(sys_socketpair, 4)                 /* 1155  socketpair()          V*/
+SYS(irix_systeminfo, 3)                        /* 1156  systeminfo()         IV*/
+SYS(irix_uname, 1)                     /* 1157  uname()              IV*/
+SYS(irix_xstat, 3)                     /* 1158  xstat()               V*/
+SYS(irix_lxstat, 3)                    /* 1159  lxstat()              V*/
+SYS(irix_fxstat, 3)                    /* 1160  fxstat()              V*/
+SYS(irix_xmknod, 0)                    /* 1161  xmknod()             ?V*/
+SYS(irix_sigaction, 4)                 /* 1162  sigaction()          ?V*/
+SYS(irix_sigpending, 1)                        /* 1163  sigpending()         ?V*/
+SYS(irix_sigprocmask, 3)               /* 1164  sigprocmask()        ?V*/
+SYS(irix_sigsuspend, 0)                        /* 1165  sigsuspend()         ?V*/
+SYS(irix_sigpoll_sys, 3)               /* 1166  sigpoll_sys()        IV*/
+SYS(irix_swapctl, 2)                   /* 1167  swapctl()            IV*/
+SYS(irix_getcontext, 0)                        /* 1168  getcontext()         HV*/
+SYS(irix_setcontext, 0)                        /* 1169  setcontext()         HV*/
+SYS(irix_waitsys, 5)                   /* 1170  waitsys()            IV*/
+SYS(irix_sigstack, 2)                  /* 1171  sigstack()           HV*/
+SYS(irix_sigaltstack, 2)               /* 1172  sigaltstack()        HV*/
+SYS(irix_sigsendset, 2)                        /* 1173  sigsendset()         IV*/
+SYS(irix_statvfs, 2)                   /* 1174  statvfs()             V*/
+SYS(irix_fstatvfs, 2)                  /* 1175  fstatvfs()            V*/
+SYS(irix_unimp, 0)                     /* 1176  XXX getpmsg()        DC*/
+SYS(irix_unimp, 0)                     /* 1177  XXX putpmsg()        DC*/
+SYS(irix_lchown, 3)                    /* 1178  lchown()              V*/
+SYS(irix_priocntl, 0)                  /* 1179  priocntl()           DC*/
+SYS(irix_sigqueue, 4)                  /* 1180  sigqueue()           IV*/
+SYS(sys_readv, 3)                      /* 1181  readv()               V*/
+SYS(sys_writev, 3)                     /* 1182  writev()              V*/
+SYS(irix_truncate64, 4)                        /* 1183  truncate64() XX32bit HV*/
+SYS(irix_ftruncate64, 4)               /* 1184  ftruncate64()XX32bit HV*/
+SYS(irix_mmap64, 0)                    /* 1185  mmap64()     XX32bit HV*/
+SYS(irix_dmi, 0)                       /* 1186  dmi()                DC*/
+SYS(irix_pread, 6)                     /* 1187  pread()              IV*/
+SYS(irix_pwrite, 6)                    /* 1188  pwrite()             IV*/
+SYS(sys_fsync, 1)                      /* 1189  fdatasync()  XXPOSIX HV*/
+SYS(irix_sgifastpath, 7)               /* 1190  sgifastpath() WHEEE  IV*/
+SYS(irix_unimp, 0)                     /* 1191  XXX attr_get()       DC*/
+SYS(irix_unimp, 0)                     /* 1192  XXX attr_getf()      DC*/
+SYS(irix_unimp, 0)                     /* 1193  XXX attr_set()       DC*/
+SYS(irix_unimp, 0)                     /* 1194  XXX attr_setf()      DC*/
+SYS(irix_unimp, 0)                     /* 1195  XXX attr_remove()    DC*/
+SYS(irix_unimp, 0)                     /* 1196  XXX attr_removef()   DC*/
+SYS(irix_unimp, 0)                     /* 1197  XXX attr_list()      DC*/
+SYS(irix_unimp, 0)                     /* 1198  XXX attr_listf()     DC*/
+SYS(irix_unimp, 0)                     /* 1199  XXX attr_multi()     DC*/
+SYS(irix_unimp, 0)                     /* 1200  XXX attr_multif()    DC*/
+SYS(irix_statvfs64, 2)                 /* 1201  statvfs64()           V*/
+SYS(irix_fstatvfs64, 2)                        /* 1202  fstatvfs64()          V*/
+SYS(irix_getmountid, 2)                        /* 1203  getmountid()XXXfsids HV*/
+SYS(irix_nsproc, 5)                    /* 1204  nsproc()             IV*/
+SYS(irix_getdents64, 3)                        /* 1205  getdents64()         HV*/
+SYS(irix_unimp, 0)                     /* 1206  XXX DFS garbage      DC*/
+SYS(irix_ngetdents, 4)                 /* 1207  ngetdents() XXXeop   HV*/
+SYS(irix_ngetdents64, 4)               /* 1208  ngetdents64() XXXeop HV*/
+SYS(irix_unimp, 0)                     /* 1209  nothin'               V*/
+SYS(irix_unimp, 0)                     /* 1210  XXX pidsprocsp()       */
+SYS(irix_unimp, 0)                     /* 1211  XXX rexec()            */
+SYS(irix_unimp, 0)                     /* 1212  XXX timer_create()     */
+SYS(irix_unimp, 0)                     /* 1213  XXX timer_delete()     */
+SYS(irix_unimp, 0)                     /* 1214  XXX timer_settime()    */
+SYS(irix_unimp, 0)                     /* 1215  XXX timer_gettime()    */
+SYS(irix_unimp, 0)                     /* 1216  XXX timer_setoverrun() */
+SYS(sys_sched_rr_get_interval, 2)      /* 1217  sched_rr_get_interval()V*/
+SYS(sys_sched_yield, 0)                        /* 1218  sched_yield()         V*/
+SYS(sys_sched_getscheduler, 1)         /* 1219  sched_getscheduler()  V*/
+SYS(sys_sched_setscheduler, 3)         /* 1220  sched_setscheduler()  V*/
+SYS(sys_sched_getparam, 2)             /* 1221  sched_getparam()      V*/
+SYS(sys_sched_setparam, 2)             /* 1222  sched_setparam()      V*/
+SYS(irix_unimp, 0)                     /* 1223  XXX usync_cntl()       */
+SYS(irix_unimp, 0)                     /* 1224  XXX psema_cntl()       */
+SYS(irix_unimp, 0)                     /* 1225  XXX restartreturn()    */
+
+/* Just to pad things out nicely. */
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+SYS(irix_unimp, 0)
+
+/* YEEEEEEEEEEEEEEEEEE!!!! */
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
new file mode 100644 (file)
index 0000000..d994155
--- /dev/null
@@ -0,0 +1,1365 @@
+/*
+ * irixelf.c: Code to load IRIX ELF executables which conform to
+ *            the MIPS ABI.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Based upon work which is:
+ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
+ */
+
+#include <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(&notes[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(&notes[i], &file))
+                       goto close_coredump;
+       
+       set_fs(fs);
+
+       DUMP_SEEK(dataoff);
+       
+       for(i = 0, vma = current->mm->mmap;
+           i < segs && vma != NULL;
+           vma = vma->vm_next) {
+               unsigned long addr = vma->vm_start;
+               unsigned long len = vma->vm_end - vma->vm_start;
+               
+               if (!maydump(vma))
+                       continue;
+               i++;
+#ifdef DEBUG
+               printk("elf_core_dump: writing %08lx %lx\n", addr, len);
+#endif
+               DUMP_WRITE((void *)addr, len);
+       }
+
+       if ((off_t) file.f_pos != offset) {
+               /* Sanity check. */
+               printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n",
+                      (off_t) file.f_pos, offset);
+       }
+
+ close_coredump:
+       if (file.f_op->release)
+               file.f_op->release(inode,&file);
+
+ end_coredump:
+       set_fs(fs);
+       iput(inode);
+#ifndef CONFIG_BINFMT_ELF
+       MOD_DEC_USE_COUNT;
+#endif
+       return has_dumped;
+}
+
+__initfunc(int init_irix_binfmt(void))
+{
+       return register_binfmt(&irix_format);
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+       /* Install the COFF, ELF and XOUT loaders.
+        * N.B. We *rely* on the table being the right size with the
+        * right number of free slots...
+        */
+       return init_irix_binfmt();
+}
+
+
+void cleanup_module( void)
+{
+       /* Remove the IRIX ELF loaders. */
+       unregister_binfmt(&irix_format);
+}
+#endif
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
new file mode 100644 (file)
index 0000000..94fcf63
--- /dev/null
@@ -0,0 +1,257 @@
+/* $Id: irixioctl.c,v 1.1 1997/06/06 09:32:33 ralf Exp $
+ * irixioctl.c: A fucking mess...
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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;
+}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
new file mode 100644 (file)
index 0000000..09c1f66
--- /dev/null
@@ -0,0 +1,902 @@
+/* $Id: irixsig.c,v 1.2 1997/06/13 10:11:22 ralf Exp $
+ * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatable or what?!?!
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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, &current->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 *) &current->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(&current->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(&current->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(&current->sig->siglock);
+               *p = new_sa;
+               check_pending(sig);
+               spin_unlock_irq(&current->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(&current->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(&current->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(&current->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(&current->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;
+}
index e7d36a16202a0c0ae67ed460efe87a17b3a1023a..0896ed1c7e749e0d7b6dddf7e0e93e17c54fad85 100644 (file)
@@ -8,29 +8,18 @@
  * instead of just grabbing them. Thus setups with different IRQ numbers
  * shouldn't result in any weird surprises, and installing new handlers
  * should be easier.
- */
-
-/*
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
-/*
- * Mips support by Ralf Baechle and Andreas Busse
  *
- * The Deskstation Tyne is almost completely like an IBM compatible PC with
- * another type of microprocessor. Therefore this code is almost completely
- * the same. More work needs to be done to support Acer PICA and other
- * machines.
+ * Mips support by Ralf Baechle and Andreas Busse
  */
-
-#include <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);
 }
 
@@ -98,16 +101,11 @@ extern void interrupt(void);
 extern void fast_interrupt(void);
 extern void bad_interrupt(void);
 
-/*
- * Initial irq handlers.
- */
-static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-
-static struct irqaction *irq_action[16] = {
-         NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
-         NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
+static struct irqaction *irq_action[32] = {
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 int get_irq_list(char *buf)
@@ -115,10 +113,10 @@ int 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) ? '+' : ' ',
@@ -133,6 +131,15 @@ int get_irq_list(char *buf)
        return len;
 }
 
+atomic_t __mips_bh_counter;
+
+#ifdef __SMP__
+#error Send superfluous SMP boxes to ralf@uni-koblenz.de
+#else
+#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
+#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
+#endif
+
 /*
  * do_IRQ handles IRQ's that have been installed without the
  * SA_INTERRUPT flag: it uses the full signal-handling return
@@ -143,14 +150,23 @@ int get_irq_list(char *buf)
 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 {
        struct irqaction * action = *(irq + irq_action);
+       int do_random, cpu = smp_processor_id();
 
+       irq_enter(cpu, irq);
        kstat.interrupts[irq]++;
-       if (action->flags & SA_SAMPLE_RANDOM)
+
+       /* slow interrupts run with interrupts enabled */
+       sti();
+       action = *(irq + irq_action);
+       do_random = 0;
+        while (action) {
+               do_random |= action->flags;
+               action->handler(irq, action->dev_id, regs);
+               action = action->next;
+        }
+       if (do_random & SA_SAMPLE_RANDOM)
                add_interrupt_randomness(irq);
-       while (action) {
-           action->handler(irq, action->dev_id, regs);
-           action = action->next;
-       }
+       irq_exit(cpu, irq);
 }
 
 /*
@@ -160,18 +176,70 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
  */
 asmlinkage void do_fast_IRQ(int irq)
 {
-       struct irqaction * action = *(irq + irq_action);
+       struct irqaction * action;
+       int do_random, cpu = smp_processor_id();
 
+       irq_enter(cpu, irq);
        kstat.interrupts[irq]++;
-       if (action->flags & SA_SAMPLE_RANDOM)
-               add_interrupt_randomness(irq);
+       action = *(irq + irq_action);
+       do_random = 0;
        while (action) {
-           action->handler(irq, action->dev_id, NULL);
-           action = action->next;
+               do_random |= action->flags;
+               action->handler(irq, action->dev_id, NULL);
+               action = action->next;
        }
+       if (do_random & SA_SAMPLE_RANDOM)
+               add_interrupt_randomness(irq);
+       irq_exit(cpu, irq);
 }
 
-#define SA_PROBE SA_ONESHOT
+/*
+ * Used only for setup of PC style interrupts and therefore still
+ * called setup_x86_irq.  Later on I'll provide a machine specific
+ * function with similar purpose.  Idea is to put all interrupts
+ * in a single table and differenciate them just by number.
+ */
+int setup_x86_irq(int irq, struct irqaction * new)
+{
+       int shared = 0;
+       struct irqaction *old, **p;
+       unsigned long flags;
+
+       p = irq_action + irq;
+       if ((old = *p) != NULL) {
+               /* Can't share interrupts unless both agree to */
+               if (!(old->flags & new->flags & SA_SHIRQ))
+                       return -EBUSY;
+
+               /* Can't share interrupts unless both are same type */
+               if ((old->flags ^ new->flags) & SA_INTERRUPT)
+                       return -EBUSY;
+
+               /* add new interrupt at end of irq queue */
+               do {
+                       p = &old->next;
+                       old = *p;
+               } while (old);
+               shared = 1;
+       }
+
+       if (new->flags & SA_SAMPLE_RANDOM)
+               rand_initialize_irq(irq);
+
+       save_flags(flags);
+       cli();
+       *p = new;
+
+       if (!shared) {
+               if (new->flags & SA_INTERRUPT)
+                       set_int_vector(irq,fast_interrupt);
+               else
+                       set_int_vector(irq,interrupt);
+               unmask_irq(irq);
+       }
+       restore_flags(flags);
+       return 0;
+}
 
 int request_irq(unsigned int irq, 
                void (*handler)(int, void *, struct pt_regs *),
@@ -179,42 +247,17 @@ int request_irq(unsigned int irq,
                const char * devname,
                void *dev_id)
 {
-       struct irqaction * action, *tmp = NULL;
-       unsigned long flags;
+       int retval;
+       struct irqaction * action;
 
-       if (irq > 15)
+       if (irq > 31)
                return -EINVAL;
        if (!handler)
-           return -EINVAL;
-       action = *(irq + irq_action);
-       if (action) {
-           if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-               for (tmp = action; tmp->next; tmp = tmp->next);
-           } else {
-               return -EBUSY;
-           }
-           if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
-             printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
-             return -EBUSY;
-           }   
-       }
-       if (irqflags & SA_SAMPLE_RANDOM)
-               rand_initialize_irq(irq);
-       save_flags(flags);
-       cli();
-       if (irq == 2)
-           action = &cascade_irq;
-       else if (irq == 13)
-         action = &math_irq;
-       else if (irq == TIMER_IRQ)
-         action = &timer_irq;
-       else
-         action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-
-       if (!action) { 
-           restore_flags(flags);
-           return -ENOMEM;
-       }
+               return -EINVAL;
+
+       action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+       if (!action)
+               return -ENOMEM;
 
        action->handler = handler;
        action->flags = irqflags;
@@ -223,116 +266,61 @@ int request_irq(unsigned int irq,
        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)
@@ -340,11 +328,6 @@ 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
@@ -357,45 +340,11 @@ int probe_irq_off (unsigned long irqs)
        return i;
 }
 
-void init_IRQ(void)
+__initfunc(void init_IRQ(void))
 {
        int i;
 
-       switch (boot_info.machtype) {
-               case MACH_MIPS_MAGNUM_4000:
-               case MACH_ACER_PICA_61:
-                       r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-                                         JAZZ_IE_ETHERNET |
-                                         JAZZ_IE_SERIAL1  |
-                                         JAZZ_IE_SERIAL2  |
-                                         JAZZ_IE_PARALLEL |
-                                         JAZZ_IE_FLOPPY);
-                       r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
-                       set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ1);
-                       /* set the clock to 100 Hz */
-                       r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
-                       break;
-               case MACH_DESKSTATION_TYNE:
-                       /* set the clock to 100 Hz */
-                       outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
-                       outb_p(LATCH & 0xff , 0x40);    /* LSB */
-                       outb(LATCH >> 8 , 0x40);        /* MSB */
-
-                       if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
-                               printk("Unable to get IRQ2 for cascade\n");
-                       break;
-               default:
-                       panic("Unknown machtype in init_IRQ");
-       }
-
-       for (i = 0; i < 16 ; i++)
+       for (i = 0; i < 32 ; i++)
                set_int_vector(i, bad_interrupt);
-
-       /* initialize the bottom half routines. */
-       for (i = 0; i < 32; i++) {
-               bh_base[i].routine = NULL;
-               bh_base[i].data = NULL;
-       }
-       bh_active = 0;
-       atomic_set(&intr_count, 0);
+       irq_setup();
 }
diff --git a/arch/mips/kernel/jazz-c.c b/arch/mips/kernel/jazz-c.c
deleted file mode 100644 (file)
index 608f337..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Jazz specific C parts
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-
-#include <asm/cachectl.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <asm/segment.h>
-
-unsigned char jazz_fd_inb(unsigned int port)
-{
-       unsigned char c;
-
-       c = *(volatile unsigned char *) port;
-       udelay(1);
-
-       return c;
-}
-
-void jazz_fd_outb(unsigned char value, unsigned int port)
-{
-       *(volatile unsigned char *) port = value;
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void jazz_fd_enable_dma(void)
-{
-       vdma_enable(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_disable_dma(void)
-{
-       vdma_disable(JAZZ_FLOPPY_DMA);
-}
-
-int jazz_fd_request_dma(void)
-{
-       return 0;
-}
-
-void jazz_fd_free_dma(void)
-{
-}
-
-void jazz_fd_clear_dma_ff(void)
-{
-}
-
-void jazz_fd_set_dma_mode(char mode)
-{
-       vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
-}
-
-void jazz_fd_set_dma_addr(unsigned int a)
-{
-       vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
-}
-
-void jazz_fd_set_dma_count(unsigned int count)
-{
-       vdma_set_count(JAZZ_FLOPPY_DMA, count);
-}
-
-int jazz_fd_get_dma_residue(void)
-{
-       return vdma_get_residue(JAZZ_FLOPPY_DMA);
-}
-
-void jazz_fd_enable_irq(void)
-{
-}
-
-void jazz_fd_disable_irq(void)
-{
-}
-
-void jazz_fd_cacheflush(unsigned char *addr, unsigned int size)
-{
-       sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-unsigned char jazz_rtc_read_data(void)
-{
-       return *(char *)JAZZ_RTC_BASE;
-}
-
-void jazz_rtc_write_data(unsigned char data)
-{
-       *(char *)JAZZ_RTC_BASE = data;
-}
diff --git a/arch/mips/kernel/jazzdma.c b/arch/mips/kernel/jazzdma.c
deleted file mode 100644 (file)
index f640981..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * jazzdma.c
- *
- * Mips Jazz DMA controller support
- * (C) 1995 Andreas Busse
- *
- * NOTE: Some of the argument checking could be removed when
- * things have settled down. Also, instead of returning 0xffffffff
- * on failure of vdma_alloc() one could leave page #0 unused
- * and return the more usual NULL pointer as logical address.
- * 
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-#include <asm/jazz.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/dma.h>
-#include <asm/jazzdma.h>
-
-
-static unsigned long vdma_pagetable_start = 0;
-static unsigned long vdma_pagetable_end = 0;
-
-/*
- * Debug stuff
- */
-#define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
-
-static int debuglvl = 3;
-
-/*
- * Local prototypes
- */
-static void vdma_pgtbl_init(void);
-
-/*
- * Initialize the Jazz R4030 dma controller
- */
-unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
-{
-    /*
-     * Allocate 32k of memory for DMA page tables.
-     * This needs to be page aligned and should be
-     * uncached to avoid cache flushing after every
-     * update.
-     */
-    vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
-    vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
-
-    /*
-     * Clear the R4030 translation table
-     */
-    vdma_pgtbl_init();
-
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
-    printk("VDMA: R4030 DMA pagetables initialized.\n");
-    return KSEG0ADDR(vdma_pagetable_end);
-}
-
-/*
- * Allocate DMA pagetables using a simple first-fit algorithm
- */
-unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
-{
-    VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int first;
-    int last;
-    int pages;
-    unsigned int frame;
-    unsigned long laddr;
-    int i;
-
-    /* check arguments */
-  
-    if (paddr > 0x1fffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
-        return VDMA_ERROR;     /* invalid physical address */
-    }
-    if (size > 0x400000 || size == 0)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid size: %08lx\n",size);
-        return VDMA_ERROR;     /* invalid physical address */
-    }
-  
-  /* find free chunk */
-    pages = (size + 4095) >> 12; /* no. of pages to allocate */
-    first = 0;
-    while (1)
-    {
-        while (entry[first].owner != VDMA_PAGE_EMPTY &&
-               first < VDMA_PGTBL_ENTRIES)
-            first++;
-        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
-            return VDMA_ERROR;
-
-        last = first+1;
-        while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
-            last++;
-    
-        if (last-first == pages)
-            break;                     /* found */
-    }
-  
-  /* mark pages as allocated */
-
-    laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
-    frame = paddr & ~(VDMA_PAGESIZE-1);
-  
-    for (i=first; i<last; i++)
-    {
-        entry[i].frame = frame;
-        entry[i].owner = laddr;
-        frame += VDMA_PAGESIZE;
-    }
-
-    /*
-     * update translation table and
-     * return logical start address
-     */
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-
-    if (vdma_debug > 1)
-        printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
-               pages,laddr);
-
-    if (vdma_debug > 2)
-    {
-        printk("LADDR: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",i<<12);
-        printk("\nPADDR: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",entry[i].frame);
-        printk("\nOWNER: ");
-        for (i=first; i<last; i++)
-            printk("%08x ",entry[i].owner);
-        printk("\n");
-    }
-  
-    return laddr;
-}
-
-/*
- * Free previously allocated dma translation pages
- * Note that this does NOT change the translation table,
- * it just marks the free'd pages as unused!
- */
-int vdma_free(unsigned long laddr)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int i;
-
-    i = laddr >> 12;
-
-    if (pgtbl[i].owner != laddr)
-    {
-        printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
-               laddr);
-        return -1;
-    }
-  
-    while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
-    {
-        pgtbl[i].owner = VDMA_PAGE_EMPTY;
-        i++;
-    }
-  
-    if (vdma_debug > 1)
-        printk("vdma_free: freed %ld pages starting from %08lx\n",
-               i-(laddr>>12),laddr);
-  
-    return 0;
-}
-
-/*
- * Map certain page(s) to another physical address.
- * Caller must have allocated the page(s) before.
- */
-int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-    int first;
-    int pages;
-
-    if (laddr > 0xffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_map: Invalid logical address: %08lx\n",laddr);
-        return -EINVAL;                /* invalid logical address */
-    }
-    if (paddr > 0x1fffffff)
-    {
-        if (vdma_debug)
-            printk("vdma_map: Invalid physical address: %08lx\n",paddr);
-        return -EINVAL;                /* invalid physical address */
-    }
-  
-    pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
-    first = laddr >> 12;
-    if (vdma_debug)
-        printk("vdma_remap: first=%x, pages=%x\n",first,pages);
-    if (first+pages > VDMA_PGTBL_ENTRIES)
-    {
-        if (vdma_debug)
-            printk("vdma_alloc: Invalid size: %08lx\n",size);
-        return -EINVAL;
-    }
-
-    paddr &= ~(VDMA_PAGESIZE-1);
-    while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
-    {
-        if (pgtbl[first].owner != laddr)
-        {
-            if (vdma_debug)
-                printk("Trying to remap other's pages.\n");
-            return -EPERM;             /* not owner */
-        }
-        pgtbl[first].frame = paddr;
-        paddr += VDMA_PAGESIZE;
-        first++;
-        pages--;
-    }
-
-    /* update translation table */
-  
-    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
-  
-    if (vdma_debug > 2)
-    {
-        int i;
-        pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
-        first = laddr >> 12;
-        printk("LADDR: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",i<<12);
-        printk("\nPADDR: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",pgtbl[i].frame);
-        printk("\nOWNER: ");
-        for (i=first; i<first+pages; i++)
-            printk("%08x ",pgtbl[i].owner);
-        printk("\n");
-    }
-      
-    return 0;
-}
-
-/*
- * Translate a physical address to a logical address.
- * This will return the logical address of the first
- * match.
- */
-unsigned long vdma_phys2log(unsigned long paddr)
-{
-    int i;
-    int frame;
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
-    frame = paddr & ~(VDMA_PAGESIZE-1);
-
-    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
-    {
-        if (pgtbl[i].frame == frame)
-            break;
-    }
-
-    if (i == VDMA_PGTBL_ENTRIES)
-        return 0xffffffff;
-
-    return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
-}
-
-/*
- * Translate a logical DMA address to a physical address
- */
-unsigned long vdma_log2phys(unsigned long laddr)
-{
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-
-    return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
-}
-  
-/*
- * Initialize the pagetable with a one-to-one mapping of
- * the first 16 Mbytes of main memory and declare all
- * entries to be unused. Using this method will at least
- * allow some early device driver operations to work.
- */
-static void vdma_pgtbl_init(void)
-{
-    int i;
-    unsigned long paddr = 0;
-    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
-  
-    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
-    {
-        pgtbl[i].frame = paddr;
-        pgtbl[i].owner = VDMA_PAGE_EMPTY;
-        paddr += VDMA_PAGESIZE;
-    }
-
-/*  vdma_stats(); */
-}
-
-/*
- * Print DMA statistics
- */
-void vdma_stats(void)
-{
-    int i;
-  
-    printk("vdma_stats: CONFIG: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_CONFIG));
-    printk("R4030 translation table base: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
-    printk("R4030 translation table limit: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
-    printk("vdma_stats: INV_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_INV_ADDR));
-    printk("vdma_stats: R_FAIL_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
-    printk("vdma_stats: M_FAIL_ADDR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
-    printk("vdma_stats: IRQ_SOURCE: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
-    printk("vdma_stats: I386_ERROR: %08x\n",
-           r4030_read_reg32(JAZZ_R4030_I386_ERROR));
-    printk("vdma_chnl_modes:   ");
-    for (i=0; i<8; i++)
-        printk("%04x ",
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
-    printk("\n");
-    printk("vdma_chnl_enables: ");
-    for (i=0; i<8; i++)
-        printk("%04x ",
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
-    printk("\n");
-}
-
-/*
- * DMA transfer functions
- */
-
-/*
- * Enable a DMA channel. Also clear any error conditions.
- */
-void vdma_enable(int channel)
-{
-    int status;
-  
-    if (vdma_debug)
-        printk("vdma_enable: channel %d\n",channel);
-  
-    /*
-     * Check error conditions first
-     */
-    status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
-    if (status & 0x400)
-        printk("VDMA: Channel %d: Address error!\n",channel);
-    if (status & 0x200)
-        printk("VDMA: Channel %d: Memory error!\n",channel);
-
-    /*
-     * Clear all interrupt flags
-     */
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
-
-    /*
-     * Enable the desired channel
-     */
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
-                      R4030_CHNL_ENABLE);
-}
-
-/*
- * Disable a DMA channel
- */
-void vdma_disable(int channel)
-{
-    if (vdma_debug)
-    {
-        int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
-
-        printk("vdma_disable: channel %d\n",channel);
-        printk("VDMA: channel %d status: %04x (%s) mode: "
-               "%02x addr: %06x count: %06x\n",
-               channel,status,((status & 0x600) ? "ERROR" : "OK"),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
-               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
-    }
-  
-    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
-                      ~R4030_CHNL_ENABLE);
-
-    /*
-     * After disabling a DMA channel a remote bus register should be
-     * read to ensure that the current DMA acknowledge cycle is completed.
-     */
-    *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
-}
-
-/*
- * Set DMA mode. This function accepts the mode values used
- * to set a PC-style DMA controller. For the SCSI and FDC
- * channels, we also set the default modes each time we're
- * called.
- * NOTE: The FAST and BURST dma modes are supported by the
- * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
- * for now.
- */
-void vdma_set_mode(int channel, int mode)
-{
-    if (vdma_debug)
-        printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
-
-    switch(channel)
-    {
-    case JAZZ_SCSI_DMA:                        /* scsi */
-        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/*                       R4030_MODE_FAST | */
-/*                       R4030_MODE_BURST | */
-                          R4030_MODE_INTR_EN |
-                          R4030_MODE_WIDTH_16 |
-                          R4030_MODE_ATIME_80);
-        break;
-      
-    case JAZZ_FLOPPY_DMA:      /* floppy */
-        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
-/*                       R4030_MODE_FAST | */
-/*                       R4030_MODE_BURST | */
-                          R4030_MODE_INTR_EN |
-                          R4030_MODE_WIDTH_8 |
-                          R4030_MODE_ATIME_120);
-        break;
-
-    case JAZZ_AUDIOL_DMA:
-    case JAZZ_AUDIOR_DMA:
-        printk("VDMA: Audio DMA not supported yet.\n");
-        break;
-      
-    default:
-        printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
-               channel);
-    }
-  
-    switch(mode)
-    {
-    case DMA_MODE_READ:
-        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
-                          ~R4030_CHNL_WRITE);
-        break;
-      
-    case DMA_MODE_WRITE:
-        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
-                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
-                          R4030_CHNL_WRITE);
-      break;
-      
-    default:
-        printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
-    }
-}
-
-/*
- * Set Transfer Address
- */
-void vdma_set_addr(int channel, long addr)
-{
-    if (vdma_debug)
-        printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
-
-    r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
-}
-
-/*
- * Set Transfer Count
- */
-void vdma_set_count(int channel, int count)
-{
-    if (vdma_debug)
-        printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
-  
-    r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
-}
-     
-/*
- * Get Residual
- */
-int vdma_get_residue(int channel)
-{
-    int residual;
-  
-    residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
-
-    if (vdma_debug)
-        printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
-  
-    return residual;
-}
diff --git a/arch/mips/kernel/magnum4000.S b/arch/mips/kernel/magnum4000.S
deleted file mode 100644 (file)
index ae176c4..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * arch/mips/kernel/magnum4000.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/stackframe.h>
-
-/*
- * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000 
- */
-               .set    noreorder
-
-               NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
-               .set    noat
-               SAVE_ALL
-               CLI
-               .set    at
-
-               /*
-                * Get pending interrupts
-                */
-               mfc0    t0,CP0_CAUSE            # get pending interrupts
-               mfc0    t1,CP0_STATUS           # get enabled interrupts
-               and     t0,t1                   # isolate allowed ones
-               andi    t0,0xff00               # isolate pending bits
-               beqz    t0,spurious_interrupt
-               sll     t0,16                   # delay slot
-
-               /*
-                * Find irq with highest priority
-                * FIXME: This is slow
-                */
-               la      t1,ll_vectors
-1:             bltz    t0,2f                   # found pending irq
-               sll     t0,1
-               b       1b
-               subu    t1,PTRSIZE              # delay slot
-
-               /*
-                * Do the low-level stuff
-                */
-2:             lw      t0,(t1)
-               jr      t0
-               nop                             # delay slot
-               END(mips_magnum_4000_handle_int)
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- */
-ll_sw0:                li      s1,~IE_SW0
-               mfc0    t0,CP0_CAUSE
-               and     t0,s1
-               mtc0    t0,CP0_CAUSE
-       PRINT("sw0 received...\n")
-               li      t1,1
-               b       call_real
-               li      t3,PTRSIZE      # delay slot, re-map to irq level 1
-
-ll_sw1:                li      s1,~IE_SW1
-               PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:  li      s1,~IE_IRQ0
-               PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:  lbu     t0,JAZZ_IO_IRQ_SOURCE
-#if __mips == 3
-               dsll    t0,1
-               ld      t0,local_vector(t0)
-#else /* 32 bit */
-               lw      t0,local_vector(t0)
-#endif
-               jr      t0
-               nop
-
-
-loc_no_irq:    PANIC("Unimplemented loc_no_irq handler")
-loc_sound:     PANIC("Unimplemented loc_sound handler")
-loc_video:     PANIC("Unimplemented loc_video handler")
-loc_scsi:      PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:  li      s1,~JAZZ_IE_KEYBOARD
-               li      t1,JAZZ_KEYBOARD_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_KEYBOARD_IRQ    # delay slot
-
-/*
- * Ethernet interrupt handler, remapped to level 2
- */
-loc_ethernet: /*       PRINT ("ethernet IRQ\n"); */
-               li      s1,~JAZZ_IE_ETHERNET
-               li      t1,JAZZ_ETHERNET_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_ETHERNET_IRQ    # delay slot
-
-
-loc_mouse:     PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1:   li      s1,~JAZZ_IE_SERIAL1
-               li      t1,JAZZ_SERIAL1_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_SERIAL1_IRQ     # delay slot
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2:   li      s1,~JAZZ_IE_SERIAL2
-               li      t1,JAZZ_SERIAL2_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_SERIAL2_IRQ     # delay slot
-
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel:  li      s1,~JAZZ_IE_PARALLEL
-               li      t1,JAZZ_PARALLEL_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_PARALLEL_IRQ    # delay slot
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy:    li      s1,~JAZZ_IE_FLOPPY
-               li      t1,JAZZ_FLOPPY_IRQ
-               b       loc_call
-               li      t3,PTRSIZE*JAZZ_FLOPPY_IRQ      # delay slot
-
-/*
- * Now call the real handler
- */
-loc_call:      lui     s3,%hi(intr_count)
-               lw      t2,%lo(intr_count)(s3)
-               la      t0,IRQ_vectors                  # delay slot
-               addiu   t2,1
-               sw      t2,%lo(intr_count)(s3)
-
-               /*
-                * Temporarily disable interrupt source
-                */
-               lhu     t2,JAZZ_IO_IRQ_ENABLE
-               addu    t0,t3                           # make ptr to IRQ handler
-               lw      t0,(t0)
-               and     t2,s1                           # delay slot
-               sh      t2,JAZZ_IO_IRQ_ENABLE
-               jalr    t0                              # call IRQ handler
-               nor     s1,zero,s1                      # delay slot
-
-               /*
-                * Reenable interrupt
-                */
-               lhu     t2,JAZZ_IO_IRQ_ENABLE
-               lw      t1,%lo(intr_count)(s3)          # delay slot
-               or      t2,s1
-               sh      t2,JAZZ_IO_IRQ_ENABLE
-
-               subu    t1,1
-               jr      v0
-               sw      t1,%lo(intr_count)(s3)
-
-ll_eisa_irq:   li      s1,~IE_IRQ2
-               PANIC("Unimplemented eisa_irq handler")
-
-ll_eisa_nmi:   li      s1,~IE_IRQ3
-               PANIC("Unimplemented eisa_nmi handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to a IBM compatible
- */
-ll_timer:      lw      t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
-               li      s1,~IE_IRQ4
-               li      t1,0
-               b       call_real
-               li      t3,0            # delay slot, re-map to irq level 0
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:      j       return
-               mtc0    zero,CP0_COMPARE
-
-/*
- * Now call the real handler
- */
-call_real:     lui     s3,%hi(intr_count)
-               lw      t2,%lo(intr_count)(s3)
-               la      t0,IRQ_vectors                  # delay slot
-               addiu   t2,1
-               sw      t2,%lo(intr_count)(s3)
-
-               /*
-                * temporarily disable interrupt
-                */
-               mfc0    t2,CP0_STATUS
-               and     t2,s1
-
-               addu    t0,t3
-               lw      t0,(t0)
-               mtc0    t2,CP0_STATUS           # delay slot
-               jalr    t0
-               nor     s1,zero,s1              # delay slot
-
-               /*
-                * reenable interrupt
-                */
-               mfc0    t2,CP0_STATUS
-               or      t2,s1
-               mtc0    t2,CP0_STATUS
-
-               lw      t2,%lo(intr_count)(s3)
-               subu    t2,1
-
-               jr      v0
-               sw      t2,%lo(intr_count)(s3)
-
-/*
- * Just for debugging...
- */
-               LEAF(drawline)
-               li      t1,0xffffffff
-               li      t2,0x100
-1:             sw      t1,(a0)
-               addiu   a0,a0,4
-               addiu   t2,t2,-1
-               bnez    t2,1b
-               nop
-               jr      ra
-               nop
-               END(drawline)
-
-
-               .data
-               PTR     ll_sw0                  # SW0
-               PTR     ll_sw1                  # SW1
-               PTR     ll_local_dma            # Local DMA
-               PTR     ll_local_dev            # Local devices
-               PTR     ll_eisa_irq             # EISA IRQ
-               PTR     ll_eisa_nmi             # EISA NMI
-               PTR     ll_timer                # Timer
-ll_vectors:    PTR     ll_count                # Count/Compare IRQ
-
-local_vector:  PTR     loc_no_irq
-               PTR     loc_parallel
-               PTR     loc_floppy
-               PTR     loc_sound
-               PTR     loc_video
-               PTR     loc_ethernet
-               PTR     loc_scsi
-               PTR     loc_keyboard
-               PTR     loc_mouse
-               PTR     loc_serial1
-               PTR     loc_serial2
-
-               .align  5
-LEAF(spurious_interrupt)
-               /*
-                * Nothing happened... (whistle)
-                */
-               lui     t1,%hi(spurious_count)
-               lw      t0,%lo(spurious_count)(t1)
-               la      v0,return
-               addiu   t0,1
-               jr      ra
-               sw      t0,%lo(spurious_count)(t1)
-               END(spurious_interrupt)
-
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
new file mode 100644 (file)
index 0000000..abcb194
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Export MIPS-specific functions needed for loadable modules.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#include <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);
diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c
new file mode 100644 (file)
index 0000000..5e71233
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * MIPS implementation of PCI BIOS services for PCI support.
+ */
+#include <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) */
diff --git a/arch/mips/kernel/pica.S b/arch/mips/kernel/pica.S
deleted file mode 100644 (file)
index 918374f..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * arch/mips/kernel/pica.S
- *
- * Copyright (C) 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- *
- * Acer PICA 61 specific stuff
- */
-#include <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)
-
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
new file mode 100644 (file)
index 0000000..0e2803d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  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;
+}
index 5c2511e273cd84a61ef41c9347ecae189170e962..3ffb9b258b6595e5b30903e10fecd0489b75fbcd 100644 (file)
@@ -2,10 +2,14 @@
  *  linux/arch/mips/kernel/process.c
  *
  *  Copyright (C) 1995 Ralf Baechle
- *  written by Ralf Baechle
  *
- * This file handles the architecture-dependent parts of initialization
+ *  Modified for R3000/DECStation support by Paul M. Antoine 1995, 1996
+ *
+ * This file handles the architecture-dependent parts of initialization,
+ * though it does not yet currently fully support the DECStation,
+ * or R3000 - PMA.
  */
+#include <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;
 
        /*
@@ -161,31 +104,35 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        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, &current->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], &current->tss.fpu, sizeof(current->tss.fpu));
 }
index b3eee95de5065beedc78c9c27e9182100dd5d817..e619115495a88bb8feedeea3848681ba374599ab 100644 (file)
@@ -1,6 +1,7 @@
 /* ptrace.c */
 /* By Ross Biro 1/23/92 */
 /* edited by Linus Torvalds */
+/* further hacked for MIPS by David S. Miller (dm@engr.sgi.com) */
 
 #include <linux/head.h>
 #include <linux/kernel.h>
@@ -8,79 +9,33 @@
 #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)) {
@@ -88,17 +43,29 @@ repeat:
                pgd_clear(pgdir);
                return 0;
        }
-       pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
+       pgmiddle = pmd_offset(pgdir, addr);
+       if (pmd_none(*pgmiddle)) {
+               handle_mm_fault(tsk, vma, addr, 0);
+               goto repeat;
+       }
+       if (pmd_bad(*pgmiddle)) {
+               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
+               pmd_clear(pgmiddle);
+               return 0;
+       }
+       pgtable = pte_offset(pgmiddle, addr);
        if (!pte_present(*pgtable)) {
-               do_no_page(vma, addr, 0);
+               handle_mm_fault(tsk, vma, addr, 0);
                goto repeat;
        }
        page = pte_page(*pgtable);
 /* this is a hack for non-kernel-mapped video buffers and similar */
-       if (page >= high_memory)
+       if (MAP_NR(page) >= MAP_NR(high_memory))
                return 0;
        page += addr & ~PAGE_MASK;
-       return *(unsigned long *) page;
+       retval = *(unsigned long *) page;
+       flush_page_to_ram(page);
+       return retval;
 }
 
 /*
@@ -110,17 +77,19 @@ repeat:
  * Now keeps R/W state of page so that a text page stays readonly
  * even if a debugger scribbles breakpoints into it.  -M.U-
  */
-static void put_long(struct vm_area_struct * vma, unsigned long addr,
+static void put_long(struct task_struct *tsk,
+                    struct vm_area_struct * vma, unsigned long addr,
        unsigned long data)
 {
        pgd_t *pgdir;
+       pmd_t *pgmiddle;
        pte_t *pgtable;
        unsigned long page;
 
 repeat:
-       pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr);
+       pgdir = pgd_offset(vma->vm_mm, addr);
        if (!pgd_present(*pgdir)) {
-               do_no_page(vma, addr, 1);
+               handle_mm_fault(tsk, vma, addr, 1);
                goto repeat;
        }
        if (pgd_bad(*pgdir)) {
@@ -128,23 +97,36 @@ repeat:
                pgd_clear(pgdir);
                return;
        }
-       pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir));
+       pgmiddle = pmd_offset(pgdir, addr);
+       if (pmd_none(*pgmiddle)) {
+               handle_mm_fault(tsk, vma, addr, 1);
+               goto repeat;
+       }
+       if (pmd_bad(*pgmiddle)) {
+               printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
+               pmd_clear(pgmiddle);
+               return;
+       }
+       pgtable = pte_offset(pgmiddle, addr);
        if (!pte_present(*pgtable)) {
-               do_no_page(vma, addr, 1);
+               handle_mm_fault(tsk, vma, addr, 1);
                goto repeat;
        }
        page = pte_page(*pgtable);
        if (!pte_write(*pgtable)) {
-               do_wp_page(vma, addr, 1);
+               handle_mm_fault(tsk, vma, addr, 1);
                goto repeat;
        }
 /* this is a hack for non-kernel-mapped video buffers and similar */
-       if (page < high_memory)
+       flush_cache_page(vma, addr);
+       if (MAP_NR(page) < MAP_NR(high_memory)) {
                *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
+               flush_page_to_ram(page);
+       }
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
        set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-       invalidate();
+       flush_tlb_page(vma, addr);
 }
 
 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
@@ -152,7 +134,7 @@ static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigne
        struct vm_area_struct * vma;
 
        addr &= PAGE_MASK;
-       vma = find_vma(tsk, addr);
+       vma = find_vma(tsk->mm, addr);
        if (!vma)
                return NULL;
        if (vma->vm_start <= addr)
@@ -186,8 +168,8 @@ static int read_long(struct task_struct * tsk, unsigned long 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;
@@ -204,7 +186,7 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
                }
                *result = low;
        } else
-               *result = get_long(vma, addr);
+               *result = get_long(tsk, vma, addr);
        return 0;
 }
 
@@ -228,8 +210,8 @@ static int write_long(struct task_struct * tsk, unsigned long 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 0: /* shouldn't happen, but safety first */
                                low = data;
@@ -253,50 +235,63 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
                                high |= data >> 8;
                                break;
                }
-               put_long(vma, addr & ~(sizeof(long)-1),low);
-               put_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
+               put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
+               put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
        } else
-               put_long(vma, addr, data);
+               put_long(tsk, vma, addr, data);
        return 0;
 }
-#endif
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
-#if 1
-       return -ENOSYS;
-#else
        struct task_struct *child;
-       struct user * dummy;
-       int i;
-
-
-       dummy = NULL;
+       int res;
 
+       lock_kernel();
+#if 0
+       printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+              (int) request, (int) pid, (unsigned long) addr,
+              (unsigned long) data);
+#endif
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
-                       return -EPERM;
+               if (current->flags & PF_PTRACED) {
+                       res = -EPERM;
+                       goto out;
+               }
                /* set the ptrace bit in the process flags. */
                current->flags |= PF_PTRACED;
-               return 0;
+               res = 0;
+               goto out;
+       }
+       if (pid == 1) {         /* you may not mess with init */
+               res = -EPERM;
+               goto out;
+       }
+       if (!(child = find_task_by_pid(pid))) {
+               res = -ESRCH;
+               goto out;
        }
-       if (pid == 1)           /* you may not mess with init */
-               return -EPERM;
-       if (!(child = find_task_by_pid(pid)))
-               return -ESRCH;
        if (request == PTRACE_ATTACH) {
-               if (child == current)
-                       return -EPERM;
+               if (child == current) {
+                       res = -EPERM;
+                       goto out;
+               }
                if ((!child->dumpable ||
                    (current->uid != child->euid) ||
+                   (current->uid != child->suid) ||
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
-                   (current->gid != child->gid)) && !suser())
-                       return -EPERM;
+                   (current->gid != child->sgid) ||
+                   (current->gid != child->gid)) && !suser()) {
+                       res = -EPERM;
+                       goto out;
+               }
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
-                       return -EPERM;
+               if (child->flags & PF_PTRACED) {
+                       res = -EPERM;
+                       goto out;
+               }
                child->flags |= PF_PTRACED;
                if (child->p_pptr != current) {
                        REMOVE_LINKS(child);
@@ -304,142 +299,148 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        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;
                }
 
 /*
@@ -448,53 +449,36 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
  * exit.
  */
                case PTRACE_KILL: {
-                       long tmp;
-
-                       if (child->state == TASK_ZOMBIE)        /* already dead */
-                               return 0;
-                       wake_up_process(child);
-                       child->exit_code = SIGKILL;
-       /* make sure the single step bit is not set. */
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-                       return 0;
-               }
-
-               case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-                       long tmp;
-
-                       if ((unsigned long) data > NSIG)
-                               return -EIO;
-                       child->flags &= ~PF_TRACESYS;
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-                       wake_up_process(child);
-                       child->exit_code = data;
-       /* give it a chance to run. */
-                       return 0;
+                       if (child->state != TASK_ZOMBIE) {
+                               wake_up_process(child);
+                               child->exit_code = SIGKILL;
+                       }
+                       res = 0;
+                       goto out;
                }
 
                case PTRACE_DETACH: { /* detach a process that was attached. */
-                       long tmp;
-
-                       if ((unsigned long) data > NSIG)
-                               return -EIO;
+                       if ((unsigned long) data > NSIG) {
+                               res = -EIO;
+                               goto out;
+                       }
                        child->flags &= ~(PF_PTRACED|PF_TRACESYS);
                        wake_up_process(child);
                        child->exit_code = data;
                        REMOVE_LINKS(child);
                        child->p_pptr = child->p_opptr;
                        SET_LINKS(child);
-                       /* make sure the single step bit is not set. */
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
-                       return 0;
+                       res = 0;
+                       goto out;
                }
 
                default:
-                       return -EIO;
+                       res = -EIO;
+                       goto out;
        }
-#endif
+out:
+       unlock_kernel();
+       return res;
 }
 
 asmlinkage void syscall_trace(void)
@@ -511,7 +495,10 @@ 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(&current->sigmask_lock);
                current->signal |= (1 << (current->exit_code - 1));
+               spin_unlock_irq(&current->sigmask_lock);
+       }
        current->exit_code = 0;
 }
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
new file mode 100644 (file)
index 0000000..2cea754
--- /dev/null
@@ -0,0 +1,138 @@
+/* $Id: r2300_fpu.S,v 1.1 1997/06/06 09:32:55 ralf Exp $
+ * r2300_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
diff --git a/arch/mips/kernel/r2300_misc.S b/arch/mips/kernel/r2300_misc.S
new file mode 100644 (file)
index 0000000..d2126b1
--- /dev/null
@@ -0,0 +1,397 @@
+/* $Id: r2300_misc.S,v 1.1 1997/06/06 09:32:57 ralf Exp $
+ * r2300_misc.S: Misc. exception handling code for R3000/R2000.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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
diff --git a/arch/mips/kernel/r2300_scall.S b/arch/mips/kernel/r2300_scall.S
new file mode 100644 (file)
index 0000000..5c6661b
--- /dev/null
@@ -0,0 +1,84 @@
+/* $Id: r2300_scall.S,v 1.1 1997/06/06 09:33:00 ralf Exp $
+ * r2300_scall.S: R2000/R3000 specific code to handle system calls.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-arch abstraction and beautification:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
new file mode 100644 (file)
index 0000000..43c44f5
--- /dev/null
@@ -0,0 +1,100 @@
+/* $Id: r2300_switch.S,v 1.1 1997/06/06 09:33:02 ralf Exp $
+ * r2300_switch.S: R3000/R2000 specific task switching code.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
+
+
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
new file mode 100644 (file)
index 0000000..1bc4538
--- /dev/null
@@ -0,0 +1,148 @@
+/* $Id: r4k_fpu.S,v 1.1 1997/06/06 09:33:04 ralf Exp $
+ * r4k_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
diff --git a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S
new file mode 100644 (file)
index 0000000..42776ab
--- /dev/null
@@ -0,0 +1,189 @@
+/* $Id: r4k_misc.S,v 1.2 1997/06/12 14:18:10 ralf Exp $
+ * r4k_misc.S: Misc. exception handling code for r4k.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
diff --git a/arch/mips/kernel/r4k_scall.S b/arch/mips/kernel/r4k_scall.S
new file mode 100644 (file)
index 0000000..1897f5a
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: r4k_scall.S,v 1.1 1997/06/06 09:33:08 ralf Exp $
+ * r4k_scall.S: R4xx0 specific code to handle system calls.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-arch abstraction and beautification:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
new file mode 100644 (file)
index 0000000..97e2530
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * r4k_switch.S: R4xx0 specific task switching code.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
diff --git a/arch/mips/kernel/r4xx0.S b/arch/mips/kernel/r4xx0.S
deleted file mode 100644 (file)
index 9b26854..0000000
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * arch/mips/kernel/r4xx0.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * This file contains most of the R4xx0 specific routines.  Due to the
- * similarities this should hopefully also be fine for the R10000.  For
- * now we especially support the R10000 by not invalidating entries out of
- * the TLB before calling the C handlers.
- *
- * This code is evil magic. Read appendix f (coprocessor 0 hazards) of
- * all R4xx0 manuals and think about that MIPS means "Microprocessor without
- * Interlocked Pipeline Stages" before you even think about changing this code!
- */
-#include <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)
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
new file mode 100644 (file)
index 0000000..215e050
--- /dev/null
@@ -0,0 +1,100 @@
+/* $Id: r6000_fpu.S,v 1.1 1997/06/06 09:33:14 ralf Exp $
+ * r6000_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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)
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
new file mode 100644 (file)
index 0000000..143449a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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();
+}
index e80a4f397e531df84b21473c7528030bd33761f4..1b00365a686818464aebe0e202985c8d263f38bb 100644 (file)
@@ -2,11 +2,13 @@
  *  linux/arch/mips/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Copyright (C) 1995  Ralf Baechle
+ *  Copyright (C) 1995, 1996  Ralf Baechle
+ *  Copyright (C) 1996  Stoned Elipot
  */
 #include <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
  */
@@ -214,137 +105,142 @@ struct bootinfo boot_info = BOOT_INFO;
 #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 */
index 7cc537294e4dea4d640c0f7b0c9380955b149471..4f975af1ae25947d0a1392fcf837fc75d83ff5b8 100644 (file)
@@ -2,7 +2,9 @@
  *  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(&current->sigmask_lock);
        mask = current->blocked;
        current->blocked = set & _BLOCKABLE;
-       regs->reg2 = -EINTR;
+       spin_unlock_irq(&current->sigmask_lock);
+
+       regs->regs[2] = -EINTR;
        while (1) {
                current->state = TASK_INTERRUPTIBLE;
                schedule();
-               if (do_signal(mask,regs))
-                       goto out;
+               if (do_signal(mask, regs))
+                       return -EINTR;
        }
-out:
-       unlock_kernel();
-       return ret;
+       return -EINTR;
 }
 
-/*
- * This sets regs->reg29 even though we don't actually use sigstacks yet..
- */
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
-       struct sigcontext_struct *context;
-       int ret;
+       struct sigcontext *context;
+       int i;
 
-       lock_kernel();
-       /*
-        * We don't support fixing ADEL/ADES exceptions for signal stack frames.
-        * No big loss - who doesn't care about the alignment of this stack
-        * really deserves to loose.
-        */
-       context = (struct sigcontext_struct *) regs->reg29;
-       if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
-           (regs->reg29 & 3))
+       context = (struct sigcontext *)(long) regs->regs[29];
+       if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
+           (regs->regs[29] & (SZREG - 1)))
                goto badframe;
 
-       current->blocked = context->sc_oldmask & _BLOCKABLE;
-       regs->reg1  = context->sc_at;
-       regs->reg2  = context->sc_v0;
-       regs->reg3  = context->sc_v1;
-       regs->reg4  = context->sc_a0;
-       regs->reg5  = context->sc_a1;
-       regs->reg6  = context->sc_a2;
-       regs->reg7  = context->sc_a3;
-       regs->reg8  = context->sc_t0;
-       regs->reg9  = context->sc_t1;
-       regs->reg10 = context->sc_t2;
-       regs->reg11 = context->sc_t3;
-       regs->reg12 = context->sc_t4;
-       regs->reg13 = context->sc_t5;
-       regs->reg14 = context->sc_t6;
-       regs->reg15 = context->sc_t7;
-       regs->reg16 = context->sc_s0;
-       regs->reg17 = context->sc_s1;
-       regs->reg18 = context->sc_s2;
-       regs->reg19 = context->sc_s3;
-       regs->reg20 = context->sc_s4;
-       regs->reg21 = context->sc_s5;
-       regs->reg22 = context->sc_s6;
-       regs->reg23 = context->sc_s7;
-       regs->reg24 = context->sc_t8;
-       regs->reg25 = context->sc_t9;
+       current->blocked = context->sc_sigset & _BLOCKABLE;
+       regs->cp0_epc = context->sc_pc;
+
        /*
-        * Skip k0/k1
+        * We only allow user processes in 64bit mode (n32, 64 bit ABI) to
+        * restore the upper half of registers.
         */
-       regs->reg28 = context->sc_gp;
-       regs->reg29 = context->sc_sp;
-       regs->reg30 = context->sc_fp;
-       regs->reg31 = context->sc_ra;
-       regs->cp0_epc = context->sc_epc;
-       regs->cp0_cause = context->sc_cause;
+       if (read_32bit_cp0_register(CP0_STATUS) & ST0_UX)
+               for(i = 31;i >= 0;i--)
+                       __get_user(regs->regs[i], &context->sc_regs[i]);
+       else
+               for(i = 31;i >= 0;i--) {
+                       __get_user(regs->regs[i], &context->sc_regs[i]);
+                       regs->regs[i] = (int) regs->regs[i];
+               }
+
+       __get_user(regs->hi, &context->sc_mdhi);
+       __get_user(regs->lo, &context->sc_mdlo);
+       restore_fp_context(context);
 
        /*
-        * disable syscall checks
+        * Disable syscall checks
         */
        regs->orig_reg2 = -1;
-       goto out;
+
+       /*
+        * Don't let your children do this ...
+        */
+       __asm__ __volatile__(
+               "move\t$29,%0\n\t"
+               "j\tret_from_sys_call"
+               :/* no outputs */
+               :"r" (regs));
+       /* Unreached */
 
 badframe:
+       lock_kernel();
        do_exit(SIGSEGV);
-out:
-       ret = context->sc_v0;
        unlock_kernel();
-       return ret;
 }
 
 /*
@@ -137,14 +128,14 @@ out:
  * one parameters in a0 (signum).
  *
  *     usp ->  [unused]                         ; first free word on stack
- *             arg save space                   ; 16 bytes argument save space
- *            code1   (addiu sp,#1-offset)     ; syscall number
+ *             arg save space                   ; 16/32 bytes arg. save space
+ *            code1   (addiu sp,#1-offset)     ; pop stackframe
  *            code2   (li v0,__NR_sigreturn)   ; syscall number
  *            code3   (syscall)                ; do sigreturn(2)
- *     #1|     at, v0, v1, a0, a1, a2, a3       ; All integer registers
- *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; except zero, k0 and k1
+ *     #1|     $0, at, v0, v1, a0, a1, a2, a3   ; All integer registers
+ *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; $0, k0 and k1 are placeholders
  *       |     s0, s1, s2, s3, s4, s5, s6, s7
- *       |     t8, t9, gp, sp, fp, ra;
+ *       |     k0, k1, t8, t9, gp, sp, fp, ra;
  *       |     epc                              ; old program counter
  *       |     cause                            ; CP0 cause register
  *       |     oldmask
@@ -153,27 +144,25 @@ out:
 struct sc {
        unsigned long   ass[4];
        unsigned int    code[4];
-       struct sigcontext_struct scc;
+       struct sigcontext scc;
 };
 #define scc_offset ((size_t)&((struct sc *)0)->scc)
 
-static void setup_frame(struct sigaction * sa, struct sc **fp,
-                        unsigned long pc, struct pt_regs *regs,
+static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
                         int signr, unsigned long oldmask)
 {
        struct sc *frame;
+       struct sigcontext *sc;
+       int i;
 
-       frame = *fp;
+       /* Align the stackframe to an adequate boundary for the architecture. */
+       frame = (struct sc *) (long) regs->regs[29];
        frame--;
+       frame = (struct sc *)((unsigned long)frame & ALMASK);
 
-       /*
-        * We don't support fixing ADEL/ADES exceptions for signal stack frames.
-        * No big loss - who doesn't care about the alignment of this stack
-        * really deserves to loose.
-        */
-       if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
-           ((unsigned long)frame & 3))
-               do_exit(SIGSEGV);
+       if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
+               goto segv_and_exit;
+       sc = &frame->scc;
 
        /*
         * Set up the return code ...
@@ -184,64 +173,83 @@ static void setup_frame(struct sigaction * sa, struct sc **fp,
         *         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(&current->sigmask_lock);
+               current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+               spin_unlock_irq(&current->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
@@ -253,16 +261,15 @@ static void setup_frame(struct sigaction * sa, struct sc **fp,
  */
 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, &current->signal);
@@ -279,7 +286,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                        if (signr == SIGSTOP)
                                continue;
                        if (_S(signr) & current->blocked) {
+                               spin_lock_irq(&current->sigmask_lock);
                                current->signal |= _S(signr);
+                               spin_unlock_irq(&current->sigmask_lock);
                                continue;
                        }
                        sa = current->sig->action + signr - 1;
@@ -288,7 +297,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                        if (signr != SIGCHLD)
                                continue;
                        /* check for SIGCHLD: it's special */
-                       while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+                       while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
                                /* nothing */;
                        continue;
                }
@@ -299,7 +308,10 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                        case SIGCONT: case SIGCHLD: case SIGWINCH:
                                continue;
 
-                       case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+                       case SIGTSTP: case SIGTTIN: case SIGTTOU:
+                               if (is_orphaned_pgrp(current->pgrp))
+                                       continue;
+                       case SIGSTOP:
                                if (current->flags & PF_PTRACED)
                                        continue;
                                current->state = TASK_STOPPED;
@@ -311,68 +323,58 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                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(&current->sigmask_lock);
                                current->signal |= _S(signr & 0x7f);
+                               spin_unlock_irq(&current->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;
 }
index a8839bb1abf84c9a28ad34fddd00f2f5ab87291e..2faf604c7f1c85c2e01da81db9cfdb93ca3f4369 100644 (file)
@@ -5,8 +5,16 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ *
+ * TODO:  Implement the compatibility syscalls.
+ *        Don't waste that much memory for empty entries in the syscall
+ *        table.
  */
+#undef CONF_PRINT_SYSCALLS
+#undef CONF_DEBUG_IRIX
+
+#include <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;
@@ -88,28 +102,28 @@ out:
 
 asmlinkage int sys_fork(struct pt_regs *regs)
 {
-       int ret;
+       int res;
 
        lock_kernel();
-       ret = do_fork(SIGCHLD, regs->reg29, regs);
+       res = do_fork(SIGCHLD, regs->regs[29], regs);
        unlock_kernel();
-       return ret;
+       return res;
 }
 
 asmlinkage int sys_clone(struct pt_regs *regs)
 {
        unsigned long clone_flags;
        unsigned long newsp;
-       int ret;
+       int res;
 
        lock_kernel();
-       clone_flags = regs->reg4;
-       newsp = regs->reg5;
+       clone_flags = regs->regs[4];
+       newsp = regs->regs[5];
        if (!newsp)
-               newsp = regs->reg29;
-       ret = do_fork(clone_flags, newsp, regs);
+               newsp = regs->regs[29];
+       res = do_fork(clone_flags, newsp, regs);
        unlock_kernel();
-       return ret;
+       return res;
 }
 
 /*
@@ -117,72 +131,136 @@ asmlinkage int sys_clone(struct pt_regs *regs)
  */
 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;
 
@@ -191,37 +269,64 @@ void do_sys(struct pt_regs *regs)
                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
        {
@@ -230,25 +335,49 @@ void do_sys(struct pt_regs *regs)
                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;
 }
index 1f96105ec137bd1c315b3be33a63f91d9db1bab0..60f58297d982807bb4a933e999a837454d1f32ca 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
  */
 
 /*
@@ -16,7 +16,7 @@
  *
  * The binary compatibility calls are still missing in this list.
  */
-SYS(sys_syscall, 7)                            /* 4000 */
+SYS(sys_syscall, 0)                            /* 4000 */
 SYS(sys_exit, 1)
 SYS(sys_fork, 0)
 SYS(sys_read, 3)
@@ -88,7 +88,7 @@ SYS(sys_sgetmask, 0)
 SYS(sys_ssetmask, 1)
 SYS(sys_setreuid, 2)                           /* 4070 */
 SYS(sys_setregid, 2)
-SYS(sys_sigsuspend, 3)
+SYS(sys_sigsuspend, 0)
 SYS(sys_sigpending, 1)
 SYS(sys_sethostname, 2)
 SYS(sys_setrlimit, 2)                          /* 4075 */
@@ -166,12 +166,44 @@ SYS(sys_writev, 3)
 SYS(sys_cacheflush, 3)
 SYS(sys_cachectl, 3)
 SYS(sys_sysmips, 4)
-SYS(sys_setup, 0)                              /* 4150 */
+SYS(sys_setup, 1)                              /* 4150 */
 SYS(sys_getsid, 1)
-SYS(sys_ni_syscall, 0)
-SYS(sys_ni_syscall, 0)
+SYS(sys_fdatasync, 0)
+SYS(sys_sysctl, 1)
 SYS(sys_mlock, 2)
 SYS(sys_munlock, 2)                            /* 4155 */
 SYS(sys_mlockall, 1)
 SYS(sys_munlockall, 0)
 SYS(sys_nfsservctl, 3)
+SYS(sys_sched_setparam,2)
+SYS(sys_sched_getparam,2)
+SYS(sys_sched_setscheduler,3)                  /* 4160 */
+SYS(sys_sched_getscheduler,1)
+SYS(sys_sched_yield,0)
+SYS(sys_sched_get_priority_max,1)
+SYS(sys_sched_get_priority_min,1)
+SYS(sys_sched_rr_get_interval,2)               /* 4165 */
+SYS(sys_nanosleep,2)
+SYS(sys_mremap,4)
+SYS(sys_accept, 3)
+SYS(sys_bind, 3)
+SYS(sys_connect, 3)                            /* 4170 */
+SYS(sys_getpeername, 3)
+SYS(sys_getsockname, 3)
+SYS(sys_getsockopt, 5)
+SYS(sys_listen, 2)
+SYS(sys_recv, 4)                               /* 4175 */
+SYS(sys_recvfrom, 6)
+SYS(sys_recvmsg, 3)
+SYS(sys_send, 4)
+SYS(sys_sendmsg, 3)
+SYS(sys_sendto, 6)                             /* 4180 */
+SYS(sys_setsockopt, 5)
+SYS(sys_shutdown, 2)
+SYS(sys_socket, 3)
+SYS(sys_socketpair, 4)
+SYS(sys_setresuid, 3)                          /* 4185 */
+SYS(sys_getresuid, 3)
+SYS(sys_query_module, 5)
+SYS(sys_poll, 3)
+SYS(sys_nfsservctl, 3)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
new file mode 100644 (file)
index 0000000..671eb5f
--- /dev/null
@@ -0,0 +1,2310 @@
+/* $Id: sysirix.c,v 1.1 1997/06/06 09:33:25 ralf Exp $
+ * sysirix.c: IRIX system call emulation.
+ *
+ * Copyright (C) 1996 David S. Miller
+ */
+
+#include <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(&current->real_timer)) {
+               unsigned long now = jiffies;
+               val = current->real_timer.expires;
+               add_timer(&current->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(&current->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;
+}
index d5ec3390be4ca184fc28ca46c8ae2c838cce84f9..c5e394d565f9e142ecce7a362957d07d2ce81a1b 100644 (file)
 #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?
@@ -37,7 +32,7 @@ get_max_hostname(unsigned long address)
 {
        struct vm_area_struct * vma;
 
-       vma = find_vma(current, address);
+       vma = find_vma(current->mm, address);
        if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
                return -EFAULT;
        address = vma->vm_end - address;
@@ -54,32 +49,35 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
 {
        int     *p;
        char    *name;
-       int     flags, len, retval = -EINVAL;
+       int     flags, tmp, len, retval;
 
        lock_kernel();
        switch(cmd)
        {
        case SETNAME:
-               retval = -EPERM;
-               if (!suser())
+               if (!suser()) {
+                       retval = -EPERM;
                        goto out;
+               }
                name = (char *) arg1;
-               len = get_max_hostname((unsigned long)name);
-               retval = len;
+               len = strlen_user(name);
                if (len < 0)
+                       retval = len;
                        goto out;
-               len = strnlen_user(name, retval);
-               retval = -EINVAL;
                if (len == 0 || len > __NEW_UTS_LEN)
+                       retval = -EINVAL;
                        goto out;
-               memcpy_fromfs(system_utsname.nodename, name, len);
+               copy_from_user(system_utsname.nodename, name, len);
                system_utsname.nodename[len] = '\0';
                retval = 0;
                goto out;
+
        case MIPS_ATOMIC_SET:
+               /* This is broken in case of page faults and SMP ...
+                  Risc/OS fauls after maximum 20 tries with EAGAIN.  */
                p = (int *) arg1;
-               retval = -EINVAL;
-               if(verify_area(VERIFY_WRITE, p, sizeof(*p)))
+               retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
+               if (retval)
                        goto out;
                save_flags(flags);
                cli();
@@ -87,18 +85,27 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
                *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;
index 2583dfa516a56b9a5fbbaacb4c81398bdfb2b462..fd57f6d0ec8252a2bedaee94d1a41daef922971e 100644 (file)
@@ -7,19 +7,26 @@
  * 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;
@@ -89,11 +138,20 @@ void do_gettimeofday(struct timeval *tv)
        cli();
        *tv = xtime;
        tv->tv_usec += do_gettimeoffset();
+
+       /*
+        * xtime is atomically updated in timer_bh. lost_ticks is
+        * nonzero if the timer bottom half hasnt executed yet.
+        */
+       if (lost_ticks)
+               tv->tv_usec += USECS_PER_JIFFY;
+
+       restore_flags(flags);
+
        if (tv->tv_usec >= 1000000) {
                tv->tv_usec -= 1000000;
                tv->tv_sec++;
        }
-       restore_flags(flags);
 }
 
 void do_settimeofday(struct timeval *tv)
@@ -114,8 +172,8 @@ 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();
 }
 
@@ -166,7 +224,7 @@ static int set_rtc_mmss(unsigned long nowtime)
 
        /* The following flags have to be released exactly in this order,
         * otherwise the DS12887 (popular MC146818A clone with integrated
-        * battery and crystal) will not reset the oscillator and will not
+        * battery and quartz) will not reset the oscillator and will not
         * update precisely 500 ms later. You won't find this mentioned in
         * the Dallas Semiconductor data sheets, but who believes data
         * sheets anyway ...                           -- Markus Kuhn
@@ -184,7 +242,7 @@ static long last_rtc_update = 0;
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static void timer_interrupt(int irq, struct pt_regs * regs)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        do_timer(regs);
 
@@ -204,7 +262,7 @@ static void timer_interrupt(int irq, struct pt_regs * 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.
@@ -238,9 +296,12 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
          )*60 + sec; /* finally seconds */
 }
 
-void time_init(void)
+static struct irqaction irq0  = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+
+void (*board_time_init)(struct irqaction *irq);
+
+__initfunc(void time_init(void))
 {
-       void (*irq_handler)(int, struct pt_regs *);
        unsigned int year, mon, day, hour, min, sec;
        int i;
 
@@ -273,14 +334,16 @@ void time_init(void)
            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);
 }
index 84c9bc14673e0a6f8cf0da6e53be82e5e127fb9e..cdbcacb434822eaa4d38e5f984d0ea7c20fee948 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  arch/mips/kernel/traps.c
+ * arch/mips/kernel/traps.c
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * 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)
 {
@@ -49,9 +54,12 @@ extern asmlinkage void deskstation_rpc44_handle_int(void);
 extern asmlinkage void deskstation_tyne_handle_int(void);
 extern asmlinkage void mips_magnum_4000_handle_int(void);
 
-extern asmlinkage void handle_mod(void);
-extern asmlinkage void handle_tlbl(void);
-extern asmlinkage void handle_tlbs(void);
+extern asmlinkage void r4k_handle_mod(void);
+extern asmlinkage void r2300_handle_mod(void);
+extern asmlinkage void r4k_handle_tlbl(void);
+extern asmlinkage void r2300_handle_tlbl(void);
+extern asmlinkage void r4k_handle_tlbs(void);
+extern asmlinkage void r2300_handle_tlbs(void);
 extern asmlinkage void handle_adel(void);
 extern asmlinkage void handle_ades(void);
 extern asmlinkage void handle_ibe(void);
@@ -71,6 +79,10 @@ extern asmlinkage void handle_reserved(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;
 
@@ -80,48 +92,54 @@ 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
@@ -141,9 +159,7 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
        }
 
        printk("\nCode : ");
-       if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
-            KSEGX(pc) == KSEG0 ||
-            KSEGX(pc) == KSEG1) &&
+       if ((KSEGX(pc) == KSEG0 || KSEGX(pc) == KSEG1) &&
            (((unsigned long) pc & 3) == 0))
        {
                for(i=0;i<5;i++)
@@ -152,230 +168,353 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
        }
        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
@@ -394,36 +533,89 @@ void trap_init(void)
 
                /*
                 * Compute mask for page_colour().  This is based on the
-                * size of the data cache.  Does the size of the icache
-                * need to be accounted for?
+                * size of the data cache.
                 */
                i = read_32bit_cp0_register(CP0_CONFIG);
                i = (i >> 26) & 7;
                page_colour_mask = 1 << (12 + i);
                break;
+       case CPU_R6000:
+       case CPU_R6000A:
+               save_fp_context = r6000_save_fp_context;
+               restore_fp_context = r6000_restore_fp_context;
+#if 0
+               /*
+                * The R6000 is the only R-series CPU that features a machine
+                * check exception (similar to the R4000 cache error) and
+                * unaligned ldc1/sdc1 exception.  The handlers have not been
+                * written yet.  Well, anyway there is no R6000 machine on the
+                * current list of targets for Linux/MIPS.
+                */
+               set_except_vector(14, handle_mc);
+               set_except_vector(15, handle_ndc);
+#endif
        case CPU_R2000:
        case CPU_R3000:
        case CPU_R3000A:
+               /*
+                * Actually don't know about these, but let's guess - PMA
+                */
+               memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
+               do_syscalls = r2300_do_syscalls;
+               save_fp_context = r2300_save_fp_context;
+               restore_fp_context = r2300_restore_fp_context;
+               resume = r2300_resume;
+               set_except_vector(1, r2300_handle_mod);
+               set_except_vector(2, r2300_handle_tlbl);
+               set_except_vector(3, r2300_handle_tlbs);
+               set_except_vector(4, handle_adel);
+               set_except_vector(5, handle_ades);
+               /*
+                * The Data Bus Error/ Instruction Bus Errors are signaled
+                * by external hardware.  Therefore these two expection have
+                * board specific handlers.
+                */
+               set_except_vector(6, handle_ibe);
+               set_except_vector(7, handle_dbe);
+               ibe_board_handler = default_be_board_handler;
+               dbe_board_handler = default_be_board_handler;
+
+               set_except_vector(8, handle_sys);
+               set_except_vector(9, handle_bp);
+               set_except_vector(10, handle_ri);
+               set_except_vector(11, handle_cpu);
+               set_except_vector(12, handle_ov);
+               set_except_vector(13, handle_tr);
+               set_except_vector(15, handle_fpe);
+
+               /*
+                * Compute mask for page_colour().  This is based on the
+                * size of the data cache.  Does the size of the icache
+                * need to be accounted for?
+                *
+                * FIXME: is any of this necessary for the R3000, which
+                *        doesn't have a config register?
+                *        (No, the R2000, R3000 family has a physical indexed
+                *        cache and doesn't need this braindamage.)
+               i = read_32bit_cp0_register(CP0_CONFIG);
+               i = (i >> 26) & 7;
+               page_colour_mask = 1 << (12 + i);
+                */
+               break;
        case CPU_R3041:
        case CPU_R3051:
        case CPU_R3052:
        case CPU_R3081:
        case CPU_R3081E:
-       case CPU_R6000:
-       case CPU_R6000A:
        case CPU_R8000:
                printk("Detected unsupported CPU type %s.\n",
-                       cpu_names[boot_info.cputype]);
-               panic("Can't handle CPU\n");
+                       cpu_names[mips_cputype]);
+               panic("Can't handle CPU");
                break;
 
        case CPU_UNKNOWN:
        default:
                panic("Unknown CPU type");
        }
-
-       /*
-        * The interrupt handler mostly depends of the board type.
-        */
-       set_except_vector(0, feature->handle_int);
+       flush_cache_all();
 }
diff --git a/arch/mips/kernel/tyne-c.c b/arch/mips/kernel/tyne-c.c
deleted file mode 100644 (file)
index 71e3068..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Deskstation Tyne specific C parts
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/*
- * How to access the FDC's registers.
- */
-unsigned char deskstation_tyne_fd_inb(unsigned int port)
-{
-       return inb_p(port);
-}
-
-void deskstation_tyne_fd_outb(unsigned char value, unsigned int port)
-{
-       outb_p(value, port);
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-void deskstation_tyne_fd_enable_dma(void)
-{
-       enable_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_disable_dma(void)
-{
-       disable_dma(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_request_dma(void)
-{
-       return request_dma(FLOPPY_DMA, "floppy");
-}
-
-void deskstation_tyne_fd_free_dma(void)
-{
-       free_dma(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_clear_dma_ff(void)
-{
-       clear_dma_ff(FLOPPY_DMA);
-}
-
-int deskstation_tyne_fd_set_dma_mode(char mode)
-{
-       return set_dma_mode(FLOPPY_DMA, mode);
-}
-
-void deskstation_tyne_fd_set_dma_addr(unsigned int a)
-{
-       set_dma_addr(FLOPPY_DMA, addr);
-}
-
-void deskstation_tyne_fd_set_dma_count(unsigned int count)
-{
-       set_dma_count(FLOPPY_DMA, count);
-}
-
-int deskstation_tyne_fd_get_dma_residue(void)
-{
-       return get_dma_residue(FLOPPY_DMA);
-}
-
-void deskstation_tyne_fd_enable_irq(void)
-{
-       enable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_disable_irq(void)
-{
-       disable_irq(FLOPPY_IRQ);
-}
-
-void deskstation_tyne_fd_cacheflush(unsigned char *addr, unsigned int)
-{
-       sys_cacheflush((void *)addr, size, DCACHE);
-}
-
-
-/*
- * Tiny Tyne DMA buffer allocator
- *
- * Untested for a long time and changed again and again ...
- * Sorry, but no hardware to test ...
- */
-static unsigned long allocated;
-
-/*
- * Not very sophisticated, but should suffice for now...
- */
-unsigned long deskstation_tyne_dma_alloc(size_t size)
-{
-       unsigned long ret = allocated;
-       allocated += size;
-       if (allocated > boot_info.dma_cache_size)
-               ret = -1;
-       return ret;
-}
-
-void deskstation_tyne_dma_init(void)
-{
-       if (boot_info.machtype != MACH_DESKSTATION_TYNE)
-               return;
-       allocated = 0;
-       printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
-               boot_info.dma_cache_size >> 10);
-}
diff --git a/arch/mips/kernel/tyne.S b/arch/mips/kernel/tyne.S
deleted file mode 100644 (file)
index 8c80afc..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * arch/mips/kernel/tyne.S
- *
- * Deskstation Tyne specific Assembler code
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * written by Ralf Baechle and Andreas Busse
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-/*
- * Deskstation Tyne interrupt handler
- */
-               .text
-               .set    noreorder
-               .set    noat
-               .align  5
-               NESTED(deskstation_tyne_handle_int, FR_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               lui     s0,%hi(PORT_BASE)
-               li      t1,0x0f
-               sb      t1,%lo(PORT_BASE+0x20)(s0)      # poll command
-               lb      t1,%lo(PORT_BASE+0x20)(s0)      # read result
-               li      s1,1
-               bgtz    t1,Lpoll_second
-               andi    t1,t1,7
-               /*
-                * Acknowledge first pic
-                */
-               lb      t2,%lo(PORT_BASE+0x21)(s0)
-               lui     s4,%hi(cache_21)
-               lb      t0,%lo(cache_21)(s4)
-               sllv    s1,s1,t1
-               or      t0,t0,s1
-               sb      t0,%lo(cache_21)(s4)
-               sb      t0,%lo(PORT_BASE+0x21)(s0)
-               lui     s3,%hi(intr_count)
-               lw      t0,%lo(intr_count)(s3)
-               li      t2,0x20
-               sb      t2,%lo(PORT_BASE+0x20)(s0)
-               /*
-                * Now call the real handler
-                */
-               la      t3,IRQ_vectors
-               sll     t2,t1,2
-               addu    t3,t3,t2
-               lw      t3,(t3)
-               addiu   t0,t0,1
-               jalr    t3
-               sw      t0,%lo(intr_count)(s3)                  # delay slot
-               lw      t0,%lo(intr_count)(s3)
-               /*
-                * Unblock first pic
-                */
-               lbu     t1,%lo(PORT_BASE+0x21)(s0)
-               lb      t1,%lo(cache_21)(s4)
-               subu    t0,t0,1
-               sw      t0,%lo(intr_count)(s3)
-               nor     s1,zero,s1
-               and     t1,t1,s1
-               sb      t1,%lo(cache_21)(s4)
-               jr      v0
-               sb      t1,%lo(PORT_BASE+0x21)(s0)      # delay slot
-
-               .align  5
-Lpoll_second:  li      t1,0x0f
-               sb      t1,%lo(PORT_BASE+0xa0)(s0)      # poll command
-               lb      t1,%lo(PORT_BASE+0xa0)(s0)      # read result
-               lui     s4,%hi(cache_A1)
-               bgtz    t1,spurious_interrupt
-               andi    t1,t1,7
-               /*
-                * Acknowledge second pic
-                */
-               lbu     t2,%lo(PORT_BASE+0xa1)(s0)
-               lb      t3,%lo(cache_A1)(s4)
-               sllv    s1,s1,t1
-               or      t3,t3,s1
-               sb      t3,%lo(cache_A1)(s4)
-               sb      t3,%lo(PORT_BASE+0xa1)(s0)
-               li      t3,0x20
-               sb      t3,%lo(PORT_BASE+0xa0)(s0)
-               lui     s3,%hi(intr_count)
-               lw      t0,%lo(intr_count)(s3)
-               sb      t3,%lo(PORT_BASE+0x20)(s0)
-               /*
-                * Now call the real handler
-                */
-               la      t0,IRQ_vectors
-               sll     t2,t1,2
-               addu    t0,t0,t2
-               lw      t0,32(t0)
-               addiu   t0,t0,1
-               jalr    t0
-               sw      t0,%lo(intr_count)(s3)                  # delay slot
-               lw      t0,%lo(intr_count)(s3)
-               /*
-                * Unblock second pic
-                */
-               lb      t1,%lo(PORT_BASE+0xa1)(s0)
-               lb      t1,%lo(cache_A1)(s4)
-               subu    t0,t0,1
-               lw      t0,%lo(intr_count)(s3)
-               nor     s1,zero,s1
-               and     t1,t1,s1
-               sb      t1,%lo(cache_A1)(s4)
-               jr      v0
-               sb      t1,%lo(PORT_BASE+0xa1)(s0)      # delay slot
-               END(deskstation_tyne_handle_int)
-
-               .align  5
-LEAF(spurious_interrupt)
-               /*
-                * Nothing happened... (whistle)
-                */
-               lui     t1,%hi(spurious_count)
-               lw      t0,%lo(spurious_count)(t1)
-               la      v0,return
-               addiu   t0,1
-               jr      ra
-               sw      t0,%lo(spurious_count)(t1)
-               END(spurious_interrupt)
-
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
new file mode 100644 (file)
index 0000000..696244b
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * Handle unaligned accesses by emulation.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * This file contains exception handler for address error exception with the
+ * special capability to execute faulting instructions in software.  The
+ * handler does not try to handle the case when the program counter points
+ * to an address not aligned to a word boundary.
+ *
+ * Putting data to unaligned addresses is a bad practice even on Intel where
+ * only the performance is affected.  Much worse is that such code is non-
+ * portable.  Due to several programs that die on MIPS due to alignment
+ * problems I decieded to implement this handler anyway though I originally
+ * didn't intend to do this at all for user code.
+ *
+ * For now I enable fixing of address errors by default to make life easier.
+ * I however intend to disable this somewhen in the future when the alignment
+ * problems with user programs have been fixed.  For programmers this is the
+ * right way to go.
+ *
+ * Fixing address errors is a per process option.  The option is inherited
+ * across fork(2) and execve(2) calls.  If you really want to use the
+ * option in your user programs - I discourage the use of the software
+ * emulation strongly - use the following code in your userland stuff:
+ *
+ * #include <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;
+}
index 454b35fe000c90b3ef76ec066825f889b2273d23..c0c775fba676656fef651b0369708ea9e5bdae83 100644 (file)
@@ -6,9 +6,8 @@
  */
 #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;
 }
diff --git a/arch/mips/ld.script b/arch/mips/ld.script
deleted file mode 100644 (file)
index 26464d9..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-OUTPUT_FORMAT("elf32-littlemips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .rel.text      : { *(.rel.text)      }
-  .rela.text     : { *(.rela.text)     }
-  .rel.data      : { *(.rel.data)      }
-  .rela.data     : { *(.rela.data)     }
-  .rel.rodata    : { *(.rel.rodata)    }
-  .rela.rodata   : { *(.rela.rodata)   }
-  .rel.got       : { *(.rel.got)       }
-  .rela.got      : { *(.rela.got)      }
-  .rel.ctors     : { *(.rel.ctors)     }
-  .rela.ctors    : { *(.rela.ctors)    }
-  .rel.dtors     : { *(.rel.dtors)     }
-  .rela.dtors    : { *(.rela.dtors)    }
-  .rel.init      : { *(.rel.init)      }
-  .rela.init     : { *(.rela.init)     }
-  .rel.fini      : { *(.rel.fini)      }
-  .rela.fini     : { *(.rela.fini)     }
-  .rel.bss       : { *(.rel.bss)       }
-  .rela.bss      : { *(.rela.bss)      }
-  .rel.plt       : { *(.rel.plt)       }
-  .rela.plt      : { *(.rela.plt)      }
-  .init          : { *(.init)          } =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  _fbss = .;
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-   *(.sbss)
-   *(.scommon)
-  }
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff --git a/arch/mips/ld.script.big b/arch/mips/ld.script.big
new file mode 100644 (file)
index 0000000..88da749
--- /dev/null
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-bigmips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)      }
+  .rela.text     : { *(.rela.text)     }
+  .rel.data      : { *(.rel.data)      }
+  .rela.data     : { *(.rela.data)     }
+  .rel.rodata    : { *(.rel.rodata)    }
+  .rela.rodata   : { *(.rela.rodata)   }
+  .rel.got       : { *(.rel.got)       }
+  .rela.got      : { *(.rela.got)      }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.init      : { *(.rel.init)      }
+  .rela.init     : { *(.rela.init)     }
+  .rel.fini      : { *(.rel.fini)      }
+  .rela.fini     : { *(.rela.fini)     }
+  .rel.bss       : { *(.rel.bss)       }
+  .rela.bss      : { *(.rela.bss)      }
+  .rel.plt       : { *(.rel.plt)       }
+  .rela.plt      : { *(.rela.plt)      }
+  .init          : { *(.init)          } =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff --git a/arch/mips/ld.script.little b/arch/mips/ld.script.little
new file mode 100644 (file)
index 0000000..26464d9
--- /dev/null
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)      }
+  .rela.text     : { *(.rela.text)     }
+  .rel.data      : { *(.rel.data)      }
+  .rela.data     : { *(.rela.data)     }
+  .rel.rodata    : { *(.rel.rodata)    }
+  .rela.rodata   : { *(.rela.rodata)   }
+  .rel.got       : { *(.rel.got)       }
+  .rela.got      : { *(.rela.got)      }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.init      : { *(.rel.init)      }
+  .rela.init     : { *(.rela.init)     }
+  .rel.fini      : { *(.rel.fini)      }
+  .rela.fini     : { *(.rela.fini)     }
+  .rel.bss       : { *(.rel.bss)       }
+  .rela.bss      : { *(.rela.bss)      }
+  .rel.plt       : { *(.rel.plt)       }
+  .rela.plt      : { *(.rela.plt)      }
+  .init          : { *(.init)          } =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
index 5fb44a4273243613233fb4838343f81c1ae23cbc..9c0639250c717f150968ce1efc84057a3030e0e3 100644 (file)
@@ -1,9 +1,6 @@
 #
 # Makefile for MIPS-specific library files..
 #
-# Many of these routines are just left over debugging trash of ancient
-# times when I just make my Tyne beep and so ...
-#
 
 .S.s:
        $(CPP) $(CFLAGS) $< -o $*.s
@@ -11,6 +8,13 @@
        $(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS = beep.o checksum.o csum.o dump_tlb.o tinycon.o watch.o
+L_OBJS = checksum.o copy_user.o csum.o dump_tlb.o io.o \
+         memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o
+
+ifdef CONFIG_DECSTATION
+L_OBJS += pmaxcon.o pmaxio.o
+else
+L_OBJS += tinycon.o
+endif
 
 include $(TOPDIR)/Rules.make
index 7e4625f20f4cb4055b0de6d92e9a52d6361922a4..ee48f659a91d3ee435057b9216331d4e1870e228 100644 (file)
  */
 #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 ...
@@ -146,3 +105,23 @@ unsigned int csum_partial_copy(const char *src, char *dst,
 
        return sum;
 }
+
+/*
+ * Copy from userspace and compute checksum.  If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+                                          int len, unsigned int sum,
+                                          int *err_ptr)
+{
+        int *dst_err_ptr=NULL;
+       int missing;
+
+       missing = copy_from_user(dst, src, len);
+       if (missing) {
+               memset(dst + len - missing, 0, missing);
+               *err_ptr = -EFAULT;
+       }
+               
+       return csum_partial(dst, len, sum);
+}
diff --git a/arch/mips/lib/copy_user.S b/arch/mips/lib/copy_user.S
new file mode 100644 (file)
index 0000000..ea691f4
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * arch/mips/mips1/memcpy.S
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996 by Ralf Baechle
+ *
+ * Less stupid memcpy/user_copy implementation for 32 bit MIPS CPUs.
+ */
+#include <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
diff --git a/arch/mips/lib/csum.S b/arch/mips/lib/csum.S
new file mode 100644 (file)
index 0000000..08224e8
--- /dev/null
@@ -0,0 +1,25 @@
+#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)
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
new file mode 100644 (file)
index 0000000..5535080
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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++);
+       }
+}
diff --git a/arch/mips/lib/io.c b/arch/mips/lib/io.c
new file mode 100644 (file)
index 0000000..c3c3f68
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * include/asm-mips/string.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1994, 1995, 1996 by Ralf Baechle
+ *
+ * For now io.c contains only the definition of isa_slot_offset.  The
+ * real io.S doesn't assemble due to a GAS bug.
+ */
+
+/*
+ * port_base is the begin of the address space to which x86 style
+ * I/O ports are mapped.
+ */
+unsigned long port_base;
+
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
+ */
+unsigned long isa_slot_offset;
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
new file mode 100644 (file)
index 0000000..95639cb
--- /dev/null
@@ -0,0 +1,221 @@
+/* memcpy.S: Mips optimized memcpy based upon SparcLinux code.
+ *
+ *  Copyright(C) 1995 Linus Torvalds
+ *  Copyright(C) 1996 David S. Miller
+ *  Copyright(C) 1996 Eddie C. Dost
+ *
+ * derived from:
+ *     e-mail between David and Eddie.
+ */
+
+#include <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
diff --git a/arch/mips/lib/memset.c b/arch/mips/lib/memset.c
new file mode 100644 (file)
index 0000000..bbdbcbb
--- /dev/null
@@ -0,0 +1,71 @@
+/* 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;
+}
diff --git a/arch/mips/lib/pmaxcon.c b/arch/mips/lib/pmaxcon.c
new file mode 100644 (file)
index 0000000..3b2cb12
--- /dev/null
@@ -0,0 +1,150 @@
+/* ----------------------------------------------------------------------
+ * console.c
+ *
+ * Copyright (C) 1994 by Waldorf Electronic,
+ * written by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1995 Paul M. Antoine (PMAX)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ * ---------------------------------------------------------------------- */
+/*
+ * FIXME: This file is hacked to be hardwired for the Personal DECStation
+ *        Only thought of as a debugging console output
+ */
+
+#include <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 */
diff --git a/arch/mips/lib/pmaxio.S b/arch/mips/lib/pmaxio.S
new file mode 100644 (file)
index 0000000..66e216a
--- /dev/null
@@ -0,0 +1,40 @@
+#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
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S
new file mode 100644 (file)
index 0000000..c42144b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * arch/mips/lib/strlen_user.S
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996 by Ralf Baechle
+ */
+#include <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
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
new file mode 100644 (file)
index 0000000..f942740
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * arch/mips/lib/strncpy_user.S
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996 by Ralf Baechle
+ */
+#include <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
diff --git a/arch/mips/lib/tags.c b/arch/mips/lib/tags.c
new file mode 100644 (file)
index 0000000..9a2e3cd
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  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;
+}
diff --git a/arch/mips/lib/tinycon.c b/arch/mips/lib/tinycon.c
new file mode 100644 (file)
index 0000000..ba25982
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * arch/mips/lib/console.c
+ *
+ * Copyright (C) 1994 by Waldorf Electronic,
+ * written by Ralf Baechle and Andreas Busse
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * FIXME: This file is hacked to be hardwired for the Deskstation
+ *        Only thought as a debugging console output.  It's as inefficient
+ *        as a piece of code can be but probably a good piece of code to
+ *        implement a preliminary console for a new target.
+ */
+
+#include <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 */
diff --git a/arch/mips/lib/watch.S b/arch/mips/lib/watch.S
new file mode 100644 (file)
index 0000000..0963752
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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)
index d7049a660cc665f9ba2c52d1aae0ffa5edbe9063..1205b2bf394b5f4cc2515c7e554561062a6c735f 100644 (file)
@@ -8,6 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS  := fault.o init.o
+O_OBJS  := extable.o init.o fault.o r4xx0.o r2300.o r6000.o tfp.o \
+            andes.o loadmmu.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mm/andes.c b/arch/mips/mm/andes.c
new file mode 100644 (file)
index 0000000..5623c98
--- /dev/null
@@ -0,0 +1,101 @@
+/* $Id: andes.c,v 1.1 1997/06/06 09:34:31 ralf Exp $
+ * andes.c: MMU and cache operations for the R10000 (ANDES).
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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();
+}
diff --git a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c
new file mode 100644 (file)
index 0000000..a92fdc4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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;
+}
index 9dc43e76f4ff0a5b6e5e4f3cbe26e7c6eafc0fbd..3ad703b1fbf3c81406afe67929a99fb7b8c79115 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  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)
@@ -56,29 +70,55 @@ good_area:
                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();
 }
index fdc3cfdf94b913d3f6c546e606a9432d0c683e9f..7a4b6df4bb69bf281a99326e45f0c27a70688a2f 100644 (file)
 #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
@@ -48,9 +61,17 @@ pte_t * __bad_pagetable(void)
        extern char empty_bad_page_table[PAGE_SIZE];
        unsigned long page;
        unsigned long dummy1, dummy2;
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+       unsigned long dummy3;
+#endif
 
-       page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
-#if __mips__ >= 3
+       page = (unsigned long) empty_bad_page_table;
+       /*
+        * As long as we only save the low 32 bit of the 64 bit wide
+        * R4000 registers on interrupt we cannot use 64 bit memory accesses
+        * to the main memory.
+        */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
         /*
          * Use 64bit code even for Linux/MIPS 32bit on R4000
          */
@@ -69,11 +90,12 @@ pte_t * __bad_pagetable(void)
                ".set\tat\n"
                ".set\treorder"
                :"=r" (dummy1),
-                "=r" (dummy2)
-               :"r" (pte_val(BAD_PAGE)),
-                "0" (page),
-                "1" (PAGE_SIZE/8));
-#else
+                "=r" (dummy2),
+                "=r" (dummy3)
+               :"0" (page),
+                "1" (PAGE_SIZE/8),
+                "2" (pte_val(BAD_PAGE)));
+#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
        __asm__ __volatile__(
                ".set\tnoreorder\n"
                "1:\tsw\t%2,(%0)\n\t"
@@ -96,7 +118,7 @@ __zeropage(unsigned long page)
 {
        unsigned long dummy1, dummy2;
 
-#ifdef __R4000__
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
         /*
          * Use 64bit code even for Linux/MIPS 32bit on R4000
          */
@@ -115,7 +137,7 @@ __zeropage(unsigned long page)
                 "=r" (dummy2)
                :"0" (page),
                 "1" (PAGE_SIZE/8));
-#else
+#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
        __asm__ __volatile__(
                ".set\tnoreorder\n"
                "1:\tsw\t$0,(%0)\n\t"
@@ -133,9 +155,9 @@ __zeropage(unsigned long page)
 static inline void
 zeropage(unsigned long page)
 {
-       sys_cacheflush((void *)page, PAGE_SIZE, BCACHE);
+       flush_page_to_ram(page);
        sync_mem();
-       __zeropage(page + (PT_OFFSET - PAGE_OFFSET));
+       __zeropage(page);
 }
 
 pte_t __bad_page(void)
@@ -147,54 +169,6 @@ 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;
@@ -203,10 +177,10 @@ void show_mem(void)
        printk("Mem-info:\n");
        show_free_areas();
        printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+       i = max_mapnr;
        while (i-- > 0) {
                total++;
-               if (mem_map[i].reserved)
+               if (PageReserved(mem_map+i))
                        reserved++;
                else if (!atomic_read(&mem_map[i].count))
                        free++;
@@ -227,7 +201,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
 
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-       pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
+       pgd_init((unsigned long)swapper_pg_dir);
        return free_area_init(start_mem, end_mem);
 }
 
@@ -236,45 +210,75 @@ void mem_init(unsigned long start_mem, unsigned long 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));
 
@@ -290,13 +294,13 @@ void si_meminfo(struct sysinfo *val)
 {
        int i;
 
-       i = high_memory >> PAGE_SHIFT;
+       i = MAP_NR(high_memory);
        val->totalram = 0;
        val->sharedram = 0;
        val->freeram = nr_free_pages << PAGE_SHIFT;
        val->bufferram = buffermem;
        while (i-- > 0)  {
-               if (mem_map[i].reserved)
+               if (PageReserved(mem_map+i))
                        continue;
                val->totalram++;
                if (!atomic_read(&mem_map[i].count))
diff --git a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c
new file mode 100644 (file)
index 0000000..43eb70e
--- /dev/null
@@ -0,0 +1,104 @@
+/* $Id: loadmmu.c,v 1.1 1997/06/06 09:34:51 ralf Exp $
+ * loadmmu.c: Setup cpu/cache specific function ptrs at boot time.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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.");
+       }
+}
diff --git a/arch/mips/mm/r2300.c b/arch/mips/mm/r2300.c
new file mode 100644 (file)
index 0000000..276674c
--- /dev/null
@@ -0,0 +1,270 @@
+/* $Id: r2300.c,v 1.1 1997/06/06 09:35:14 ralf Exp $
+ * r2300.c: R2000 and R3000 specific mmu/cache code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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();
+}
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
new file mode 100644 (file)
index 0000000..9743430
--- /dev/null
@@ -0,0 +1,2445 @@
+/*
+ * 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();
+}
diff --git a/arch/mips/mm/r6000.c b/arch/mips/mm/r6000.c
new file mode 100644 (file)
index 0000000..25132d7
--- /dev/null
@@ -0,0 +1,181 @@
+/* $Id: r6000.c,v 1.1 1997/06/06 09:35:31 ralf Exp $
+ * r6000.c: MMU and cache routines for the R6000 processors.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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();
+}
diff --git a/arch/mips/mm/tfp.c b/arch/mips/mm/tfp.c
new file mode 100644 (file)
index 0000000..bd52c9b
--- /dev/null
@@ -0,0 +1,102 @@
+/* $Id: tfp.c,v 1.1 1997/06/06 09:35:39 ralf Exp $
+ * tfp.c: MMU and cache routines specific to the r8000 (TFP).
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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();
+}
+
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
new file mode 100644 (file)
index 0000000..025d7bb
--- /dev/null
@@ -0,0 +1,30 @@
+# $Id: Makefile,v 1.1 1997/06/06 09:36:08 ralf Exp $
+# Makefile for the SGI specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = indy_mc.o indy_hpc.o indy_int.o system.o indy_timer.o indyIRQ.o \
+       reset.o setup.o time.o
+
+all: sgikern.a
+
+sgikern.a: $(OBJS)
+       $(AR) rcs sgikern.a $(OBJS)
+       sync
+
+indyIRQ.o: indyIRQ.S
+
+dep:
+       $(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/sgi/kernel/indyIRQ.S b/arch/mips/sgi/kernel/indyIRQ.S
new file mode 100644 (file)
index 0000000..535febb
--- /dev/null
@@ -0,0 +1,129 @@
+/* $Id: indyIRQ.S,v 1.1 1997/06/06 09:36:13 ralf Exp $
+ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
+ *            Guiness.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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)
diff --git a/arch/mips/sgi/kernel/indy_hpc.c b/arch/mips/sgi/kernel/indy_hpc.c
new file mode 100644 (file)
index 0000000..4e7bf26
--- /dev/null
@@ -0,0 +1,114 @@
+/* $Id: indy_hpc.c,v 1.1 1997/06/06 09:36:18 ralf Exp $
+ * indy_hpc.c: Routines for generic manipulation of the HPC controllers.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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;
+}
diff --git a/arch/mips/sgi/kernel/indy_int.c b/arch/mips/sgi/kernel/indy_int.c
new file mode 100644 (file)
index 0000000..9f73cc5
--- /dev/null
@@ -0,0 +1,600 @@
+/* $Id: indy_int.c,v 1.1 1997/06/06 09:36:21 ralf Exp $
+ * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
+ *             found on INDY workstations..
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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
+}
diff --git a/arch/mips/sgi/kernel/indy_mc.c b/arch/mips/sgi/kernel/indy_mc.c
new file mode 100644 (file)
index 0000000..039177e
--- /dev/null
@@ -0,0 +1,153 @@
+/* $Id: indy_mc.c,v 1.1 1997/06/06 09:36:24 ralf Exp $
+ * indy_mc.c: Routines for manipulating the INDY memory controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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 */
+}
diff --git a/arch/mips/sgi/kernel/indy_timer.c b/arch/mips/sgi/kernel/indy_timer.c
new file mode 100644 (file)
index 0000000..ce8fc60
--- /dev/null
@@ -0,0 +1,297 @@
+/* $Id: indy_timer.c,v 1.1 1997/06/06 09:36:28 ralf Exp $
+ * indy_timer.c: Setting up the clock on the INDY 8254 controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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();
+}
+
diff --git a/arch/mips/sgi/kernel/reset.c b/arch/mips/sgi/kernel/reset.c
new file mode 100644 (file)
index 0000000..6bb8616
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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 */
+}
diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c
new file mode 100644 (file)
index 0000000..64fa44c
--- /dev/null
@@ -0,0 +1,91 @@
+/* $Id: setup.c,v 1.1 1997/06/06 09:36:33 ralf Exp $
+ * setup.c: SGI specific setup, including init of the feature struct.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef __GOGOGO__
+#error "... about to fuckup your Indy?"
+#endif
+#include <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();
+               }
+       }
+}
diff --git a/arch/mips/sgi/kernel/system.c b/arch/mips/sgi/kernel/system.c
new file mode 100644 (file)
index 0000000..b4d9638
--- /dev/null
@@ -0,0 +1,168 @@
+/* $Id: system.c,v 1.1 1997/06/06 09:36:36 ralf Exp $
+ * system.c: Probe the system type using ARCS prom interface library.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <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");
+}
diff --git a/arch/mips/sgi/kernel/time.c b/arch/mips/sgi/kernel/time.c
new file mode 100644 (file)
index 0000000..5b53a35
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Id: time.c,v 1.1 1997/06/06 09:36:39 ralf Exp $
+ * time.c: Generic SGI time_init() code, this will dispatch to the
+ *         appropriate per-architecture time/counter init code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+extern void indy_timer_init(void);
+
+void time_init(void)
+{
+       /* XXX assume INDY for now XXX */
+       indy_timer_init();
+}
diff --git a/arch/mips/sgi/prom/Makefile b/arch/mips/sgi/prom/Makefile
new file mode 100644 (file)
index 0000000..2adab97
--- /dev/null
@@ -0,0 +1,23 @@
+# $Id: Makefile,v 1.1 1997/06/06 09:36:49 ralf Exp $
+# Makefile for the SGI arcs prom monitor library routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+OBJS  = console.o init.o printf.o memory.o tree.o tags.o env.o \
+      cmdline.o misc.o time.o file.o
+
+all: promlib.a
+
+promlib.a: $(OBJS)
+       $(AR) rcs promlib.a $(OBJS)
+       sync
+
+dep:
+       $(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/sgi/prom/cmdline.c b/arch/mips/sgi/prom/cmdline.c
new file mode 100644 (file)
index 0000000..622c0db
--- /dev/null
@@ -0,0 +1,60 @@
+/* $Id: cmdline.c,v 1.1 1997/06/06 09:36:53 ralf Exp $
+ * cmdline.c: Kernel command line creation using ARCS argc/argv.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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
+}
diff --git a/arch/mips/sgi/prom/console.c b/arch/mips/sgi/prom/console.c
new file mode 100644 (file)
index 0000000..354d824
--- /dev/null
@@ -0,0 +1,24 @@
+/* $Id: console.c,v 1.1 1997/06/06 09:36:56 ralf Exp $
+ * console.c: SGI arcs console code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+
+#include <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;
+}
diff --git a/arch/mips/sgi/prom/env.c b/arch/mips/sgi/prom/env.c
new file mode 100644 (file)
index 0000000..3e445d4
--- /dev/null
@@ -0,0 +1,20 @@
+/* $Id: env.c,v 1.1 1997/06/06 09:36:59 ralf Exp $
+ * env.c: ARCS environment variable routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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);
+}
diff --git a/arch/mips/sgi/prom/file.c b/arch/mips/sgi/prom/file.c
new file mode 100644 (file)
index 0000000..97163ab
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: file.c,v 1.1 1997/06/06 09:37:03 ralf Exp $
+ * file.c: ARCS firmware interface to files.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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);
+}
diff --git a/arch/mips/sgi/prom/init.c b/arch/mips/sgi/prom/init.c
new file mode 100644 (file)
index 0000000..4ffb025
--- /dev/null
@@ -0,0 +1,59 @@
+/* $Id: init.c,v 1.1 1997/06/06 09:37:06 ralf Exp $
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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;
+}
diff --git a/arch/mips/sgi/prom/memory.c b/arch/mips/sgi/prom/memory.c
new file mode 100644 (file)
index 0000000..293cc33
--- /dev/null
@@ -0,0 +1,129 @@
+/* $Id: memory.c,v 1.1 1997/06/06 09:37:10 ralf Exp $
+ * memory.c: PROM library functions for acquiring/using memory descriptors
+ *           given to us from the ARCS firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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;
+       }
+}
diff --git a/arch/mips/sgi/prom/misc.c b/arch/mips/sgi/prom/misc.c
new file mode 100644 (file)
index 0000000..53ee61c
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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();
+}
diff --git a/arch/mips/sgi/prom/printf.c b/arch/mips/sgi/prom/printf.c
new file mode 100644 (file)
index 0000000..801c10e
--- /dev/null
@@ -0,0 +1,34 @@
+/* $Id: printf.c,v 1.1 1997/06/06 09:37:17 ralf Exp $
+ * printf.c: Putting things on the screen using SGI arcs
+ *           PROM facilities.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+
+#include <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;
+}
diff --git a/arch/mips/sgi/prom/salone.c b/arch/mips/sgi/prom/salone.c
new file mode 100644 (file)
index 0000000..a77a978
--- /dev/null
@@ -0,0 +1,24 @@
+/* $Id: salone.c,v 1.1 1997/06/06 09:37:20 ralf Exp $
+ * salone.c: Routines to load into memory and execute stand-along
+ *           program images using ARCS PROM firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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);
+}
diff --git a/arch/mips/sgi/prom/tags.c b/arch/mips/sgi/prom/tags.c
new file mode 100644 (file)
index 0000000..595d96c
--- /dev/null
@@ -0,0 +1,67 @@
+/* $Id: tags.c,v 1.1 1997/06/06 09:37:22 ralf Exp $
+ * tags.c: Initialize the arch tags the way the MIPS kernel setup
+ *         expects.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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 */
+}
diff --git a/arch/mips/sgi/prom/time.c b/arch/mips/sgi/prom/time.c
new file mode 100644 (file)
index 0000000..e799d66
--- /dev/null
@@ -0,0 +1,17 @@
+/* $Id: time.c,v 1.1 1997/06/06 09:37:26 ralf Exp $
+ * time.c: Extracting time information from ARCS prom.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/sgialib.h>
+
+struct linux_tinfo *prom_gettinfo(void)
+{
+       return romvec->get_tinfo();
+}
+
+unsigned long prom_getrtime(void)
+{
+       return romvec->get_rtime();
+}
diff --git a/arch/mips/sgi/prom/tree.c b/arch/mips/sgi/prom/tree.c
new file mode 100644 (file)
index 0000000..76fd5e5
--- /dev/null
@@ -0,0 +1,107 @@
+/* $Id: tree.c,v 1.1 1997/06/06 09:37:29 ralf Exp $
+ * tree.c: PROM component device tree code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
new file mode 100644 (file)
index 0000000..9bd570f
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# Makefile for the SNI specific part of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: sni.o
+O_TARGET := sni.o
+O_OBJS  := hw-access.o int-handler.o io.o pci.o reset.o setup.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/sni/hw-access.c b/arch/mips/sni/hw-access.c
new file mode 100644 (file)
index 0000000..39cbec4
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Low-level hardware access stuff for SNI RM200 PCI
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#include <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
+};
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
new file mode 100644 (file)
index 0000000..d051c8b
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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)
diff --git a/arch/mips/sni/io.c b/arch/mips/sni/io.c
new file mode 100644 (file)
index 0000000..f62fdc2
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Low level I/O functions for SNI.
+ */
+#include <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);
+}
diff --git a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c
new file mode 100644 (file)
index 0000000..917d07a
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ */
+#include <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 */
diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c
new file mode 100644 (file)
index 0000000..3052d41
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  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;
+}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
new file mode 100644 (file)
index 0000000..7fa76a4
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <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;
+}
diff --git a/arch/mips/tools/Makefile b/arch/mips/tools/Makefile
new file mode 100644 (file)
index 0000000..7216277
--- /dev/null
@@ -0,0 +1,26 @@
+# Makefile for MIPS kernel build tools.
+#
+# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
+#
+TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: $(TARGET)
+
+$(TARGET): offset.h
+       cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
+
+offset.h: offset.s
+       sed -n '/^@@@/s///p' $^ >$@
+
+offset.s: offset.c
+
+clean:
+       rm -f offset.s $(TARGET).new
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c
new file mode 100644 (file)
index 0000000..a8660dc
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Made portable by Ralf Baechle
+ */
+
+#include <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) */");
index 85566667f4fb37118719dfd51382e5a0afdeeeb4..69ed624225cbdf595dd16d8436ca4d5524499de8 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.35 1997/04/07 06:54:09 davem Exp $
+# $Id: config.in,v 1.36 1997/06/17 03:54:47 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
index a6df2dcc078891c118303c161d2dfcb337bc03e2..b76742429fa804adccc204d8235c35b981ec704a 100644 (file)
@@ -64,6 +64,7 @@ CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
 CONFIG_BINFMT_JAVA=m
 
 #
@@ -103,6 +104,7 @@ CONFIG_IP_MASQUERADE=y
 # 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)
index 6354eddedee29014554044495014b8cd4a5b4f6e..00f687c926666fb7339db62e2aeae41f33ffb639 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.6 1997/04/17 20:35:42 jj Exp $
+# $Id: config.in,v 1.7 1997/06/17 03:54:52 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
index fbc4a5073b0fb8f0638e91f6e86b77bc6cd39d90..6b08fd41bbf7caea0bee9ad2a0359d02893f6923 100644 (file)
@@ -46,7 +46,7 @@ SUN_FB_CREATOR=y
 # Misc Linux/SPARC drivers
 #
 # CONFIG_SUN_OPENPROMIO is not set
-# CONFIG_SUN_MOSTEK_RTC is not set
+CONFIG_SUN_MOSTEK_RTC=y
 # CONFIG_SUN_OPENPROMFS is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
@@ -61,7 +61,8 @@ CONFIG_BINFMT_ELF32=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
 
 #
@@ -75,6 +76,7 @@ CONFIG_INET=y
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
+# CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
@@ -88,8 +90,10 @@ CONFIG_SKB_LARGE=y
 #
 #  
 #
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_IPX=y
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=y
+# CONFIG_IPDDP is not set
 # CONFIG_AX25 is not set
 
 #
@@ -134,6 +138,9 @@ CONFIG_SUNLANCE=y
 # Filesystems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_FAT_FS is not set
@@ -149,6 +156,7 @@ CONFIG_RNFS_BOOTP=y
 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
index 199360a5f26a2ffd98479c50c231d1cc23622cae..c7bb1064afbbbe557a1adc67ec058aa60704f3a5 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.22 1997/05/27 19:30:17 jj Exp $
+# $Id: Makefile,v 1.23 1997/06/06 10:56:20 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -18,7 +18,8 @@ all: kernel.o head.o init_task.o
 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
index 05d50fe566d32b3fe04eee06d6d88d302ad0255b..9ab2b7aca15eb179b538ac5f6ba1f6b4a8e5bf52 100644 (file)
@@ -6,6 +6,8 @@
 #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>
index efb1b48fcf739bba3b0aa2dce6139f1eccb373b2..e3751c326757890211b1d1baf099a2e28ea3990b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.21 1997/06/02 06:33:28 davem Exp $
+/* $Id: etrap.S,v 1.22 1997/06/13 14:02:40 davem Exp $
  * etrap.S: Preparing for entry into the kernel on Sparc V9.
  *
  * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -59,7 +59,10 @@ etrap_irq:
        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
index d3792dec6a8d77b87654976f5c57fc5d39fe5001..20c27beabccbe5e90582ecb2355c2e86a9cd5908 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.8 1997/06/04 13:05:15 jj Exp $
+/* $Id: ioctl32.c,v 1.11 1997/06/16 11:05:00 jj Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
 #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.
@@ -370,6 +376,109 @@ static inline int hdio_getgeo(unsigned int fd, u32 arg)
        return err;
 }
 
+struct  fbcmap32 {
+       int             index;          /* first element (0 origin) */
+       int             count;
+       u32             red;
+       u32             green;
+       u32             blue;
+};
+
+#define FBIOPUTCMAP32  _IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32  _IOW('F', 4, struct fbcmap32)
+
+static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg)
+{
+       struct fbcmap f;
+       int ret;
+       char red[256], green[256], blue[256];
+       u32 r, g, b;
+       unsigned long old_fs = get_fs();
+       
+       if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) ||
+           __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) ||
+           __get_user(r, &(((struct fbcmap32 *)A(arg))->red)) ||
+           __get_user(g, &(((struct fbcmap32 *)A(arg))->green)) ||
+           __get_user(b, &(((struct fbcmap32 *)A(arg))->blue)))
+               return -EFAULT;
+       if ((f.index < 0) || (f.index > 255)) return -EINVAL;
+       if (f.index + f.count > 256)
+               f.count = 256 - f.index;
+       if (cmd == FBIOPUTCMAP32) {
+               if (copy_from_user (red, (char *)A(r), f.count) ||
+                   copy_from_user (green, (char *)A(g), f.count) ||
+                   copy_from_user (blue, (char *)A(b), f.count))
+                       return -EFAULT;
+       }
+       f.red = red; f.green = green; f.blue = blue;
+       set_fs (KERNEL_DS);
+       ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP : FBIOGETCMAP, (long)&f);
+       set_fs (old_fs);
+       if (!ret && cmd == FBIOGETCMAP32) {
+               if (copy_to_user ((char *)A(r), red, f.count) ||
+                   copy_to_user ((char *)A(g), green, f.count) ||
+                   copy_to_user ((char *)A(b), blue, f.count))
+                       return -EFAULT;
+       }
+       return ret;
+}
+
+struct fbcursor32 {
+       short set;              /* what to set, choose from the list above */
+       short enable;           /* cursor on/off */
+       struct fbcurpos pos;    /* cursor position */
+       struct fbcurpos hot;    /* cursor hot spot */
+       struct fbcmap32 cmap;   /* color map info */
+       struct fbcurpos size;   /* cursor bit map size */
+       u32     image;          /* cursor image bits */
+       u32     mask;           /* cursor mask bits */
+};
+       
+#define FBIOSCURSOR32  _IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32  _IOW('F', 25, struct fbcursor32)
+
+static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg)
+{
+       struct fbcursor f;
+       int ret;
+       char red[2], green[2], blue[2];
+       char image[128], mask[128];
+       u32 r, g, b;
+       u32 m, i;
+       unsigned long old_fs = get_fs();
+       
+       if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) ||
+           __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) ||
+           __get_user(f.size.fby, &(((struct fbcursor32 *)A(arg))->size.fby)) ||
+           __get_user(f.cmap.index, &(((struct fbcursor32 *)A(arg))->cmap.index)) ||
+           __get_user(f.cmap.count, &(((struct fbcursor32 *)A(arg))->cmap.count)) ||
+           __get_user(r, &(((struct fbcursor32 *)A(arg))->cmap.red)) ||
+           __get_user(g, &(((struct fbcursor32 *)A(arg))->cmap.green)) ||
+           __get_user(b, &(((struct fbcursor32 *)A(arg))->cmap.blue)) ||
+           __get_user(m, &(((struct fbcursor32 *)A(arg))->mask)) ||
+           __get_user(i, &(((struct fbcursor32 *)A(arg))->image)))
+               return -EFAULT;
+       if (f.set & FB_CUR_SETCMAP) {
+               if ((uint) f.size.fby > 32)
+                       return -EINVAL;
+               if (copy_from_user (mask, (char *)A(m), f.size.fby * 4) ||
+                   copy_from_user (image, (char *)A(i), f.size.fby * 4))
+                       return -EFAULT;
+               f.image = image; f.mask = mask;
+       }
+       if (f.set & FB_CUR_SETCMAP) {
+               if (copy_from_user (red, (char *)A(r), 2) ||
+                   copy_from_user (green, (char *)A(g), 2) ||
+                   copy_from_user (blue, (char *)A(b), 2))
+                       return -EFAULT;
+               f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue;
+       }
+       set_fs (KERNEL_DS);
+       ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f);
+       set_fs (old_fs);
+       return ret;
+}
+       
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
        struct file * filp;
@@ -431,6 +540,15 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
        case BLKGETSIZE:
                error = w_long(fd, cmd, arg);
                goto out;
+               
+       case FBIOPUTCMAP32:
+       case FBIOGETCMAP32:
+               error = fbiogetputcmap(fd, cmd, arg);
+               goto out;
+               
+       case FBIOSCURSOR32:
+               error = fbiogscursor(fd, cmd, arg);
+               goto out;
 
        /* List here exlicitly which ioctl's are known to have
         * compatable types passed or none at all...
@@ -471,6 +589,17 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
        case TIOCSPGRP:
        case TIOCGPGRP:
        case TIOCSCTTY:
+       
+       /* Big F */
+       case FBIOGTYPE:
+       case FBIOSATTR:
+       case FBIOGATTR:
+       case FBIOSVIDEO:
+       case FBIOGVIDEO:
+       case FBIOGCURSOR32: /* This is not implemented yet. Later it should be converted... */
+       case FBIOSCURPOS:
+       case FBIOGCURPOS:
+       case FBIOGCURMAX:
 
        /* Little f */
        case FIOCLEX:
@@ -479,6 +608,10 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
        case FIONBIO:
        case FIONREAD: /* This is also TIOCINQ */
        
+       /* 0x00 */
+       case FIBMAP:
+       case FIGETBSZ:
+       
        /* 0x12 */
        case BLKRRPART:
        case BLKFLSBUF:
@@ -495,6 +628,59 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
        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:
index cc8183618d57a7e1535bffd6da5d8bbaf1ca0d69..626ad73cb4744c3f352f9d8f7a64529ae9c8e7c1 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $
+/*  $Id: process.c,v 1.18 1997/06/13 14:02:42 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -360,6 +360,7 @@ void flush_thread(void)
        }
        
        /* Now, this task is no longer a kernel thread. */
+       current->tss.current_ds = USER_DS;
        if(current->tss.flags & SPARC_FLAG_KTHREAD) {
                current->tss.flags &= ~SPARC_FLAG_KTHREAD;
 
@@ -368,8 +369,8 @@ void flush_thread(void)
                 */
                get_mmu_context(current);
        }
-       current->tss.current_ds = USER_DS;
-       spitfire_set_secondary_context (current->mm->context);
+       current->tss.ctx = current->mm->context & 0x1fff;
+       spitfire_set_secondary_context (current->tss.ctx);
 }
 
 static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
@@ -571,12 +572,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
                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;
index 165b17ef0d3702a538c19fe0341747a3ef0d5128..36999d2a055e5c0729cd7a1c50485dc224358f62 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.21 1997/06/02 07:26:54 davem Exp $
+/* $Id: rtrap.S,v 1.23 1997/06/16 07:38:41 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -25,10 +25,10 @@ rtrap:      sethi           %hi(bh_active), %l2
        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
index fe4615a6b6d55ebb083842257ebcdd1be8fa5ee7..f1e02382bf4aae8128cd8cf78498e6a5f1228b9b 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.6 1997/05/29 12:44:48 jj Exp $
+/*  $Id: signal.c,v 1.7 1997/06/16 06:49:59 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -144,19 +144,21 @@ void do_sigreturn(struct pt_regs *regs)
        }
 #endif 
        synchronize_user_stack ();
-       sf = (struct new_signal_frame *) regs->u_regs [UREG_FP];
+       sf = (struct new_signal_frame *)
+               (regs->u_regs [UREG_FP] + STACK_BIAS);
+
        /* 1. Make sure we are not getting garbage from the user */
-       if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
+       if (verify_area (VERIFY_READ, sf, sizeof (*sf)))
                goto segv;
-       }
-       if (((unsigned long) sf) & 3){
+
+       if (((unsigned long) sf) & 3)
                goto segv;
-       }
+
        get_user(tpc, &sf->info.si_regs.tpc);
        __get_user(tnpc, &sf->info.si_regs.tnpc);
-       if ((tpc | tnpc) & 3){
+       if ((tpc | tnpc) & 3)
                goto segv;
-       }
+
        regs->tpc = tpc;
        regs->tnpc = tnpc;
 
@@ -229,14 +231,15 @@ new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
        if (!current->used_math)
                sigframe_size -= sizeof(__siginfo_fpu_t);
 
-       sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
+       sf = (struct new_signal_frame *)
+               (regs->u_regs[UREG_FP] + STACK_BIAS - sigframe_size);
        
-       if (invalid_frame_pointer (sf, sigframe_size)){
+       if (invalid_frame_pointer (sf, sigframe_size)) {
                lock_kernel ();
                do_exit(SIGILL);
        }
 
-       if (current->tss.w_saved != 0){
+       if (current->tss.w_saved != 0) {
                printk ("%s[%d]: Invalid user stack frame for "
                        "signal delivery.\n", current->comm, current->pid);
                lock_kernel ();
@@ -254,8 +257,8 @@ new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
        }
 
        __put_user(oldmask, &sf->info.si_mask);
-       for (i = 0; i < sizeof(struct reg_window)/8; i++) {
-               __get_user(tmp, (((u64 *)regs->u_regs[UREG_FP])+i));
+       for (i = 0; i < sizeof(struct reg_window)/sizeof(u64); i++) {
+               __get_user(tmp, (((u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS))+i));
                __put_user(tmp, (((u64 *)sf)+i));
        }
        
@@ -264,7 +267,7 @@ new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
        __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);
index 59815b7a81ea3428ce442e6f86d9698c453b2f8a..3ecaee05f92e12d624ac907fa1f1c8509619b303 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $
+/* $Id: sys_sparc32.c,v 1.32 1997/06/17 05:36:40 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1327,13 +1327,162 @@ asmlinkage int sys32_umount(u32 name)
        return sys_umount((char *)A(name));
 }
 
+struct ncp_mount_data32 {
+        int version;
+        unsigned int ncp_fd;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_pid_t32 wdog_pid;
+        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+        unsigned int time_out;
+        unsigned int retry_count;
+        unsigned int flags;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *do_ncp_super_data_conv(void *raw_data)
+{
+       struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
+       struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+
+       n->dir_mode = n32->dir_mode;
+       n->file_mode = n32->file_mode;
+       n->gid = n32->gid;
+       n->uid = n32->uid;
+       memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
+       n->wdog_pid = n32->wdog_pid;
+       n->mounted_uid = n32->mounted_uid;
+       return raw_data;
+}
+
+struct smb_mount_data32 {
+        int version;
+        unsigned int fd;
+        __kernel_uid_t32 mounted_uid;
+        struct sockaddr_in addr;
+        char server_name[17];
+        char client_name[17];
+        char service[64];
+        char root_path[64];
+        char username[64];
+        char password[64];
+        char domain[64];
+        unsigned short max_xmit;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *do_smb_super_data_conv(void *raw_data)
+{
+       struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+       struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+
+       s->dir_mode = s32->dir_mode;
+       s->file_mode = s32->file_mode;
+       s->gid = s32->gid;
+       s->uid = s32->uid;
+       memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr)));
+       s->mounted_uid = s32->mounted_uid;
+       return raw_data;
+}
+
+static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
+{
+       int i;
+       unsigned long page;
+       struct vm_area_struct *vma;
+
+       *kernel = 0;
+       if(!user)
+               return 0;
+       vma = find_vma(current->mm, (unsigned long)user);
+       if(!vma || (unsigned long)user < vma->vm_start)
+               return -EFAULT;
+       if(!(vma->vm_flags & VM_READ))
+               return -EFAULT;
+       i = vma->vm_end - (unsigned long) user;
+       if(PAGE_SIZE <= (unsigned long) i)
+               i = PAGE_SIZE - 1;
+       if(!(page = __get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+       if(copy_from_user((void *) page, user, i)) {
+               free_page(page);
+               return -EFAULT;
+       }
+       *kernel = page;
+       return 0;
+}
+
 extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
                                unsigned long new_flags, void *data);
 
+#define SMBFS_NAME     "smbfs"
+#define NCPFS_NAME     "ncpfs"
+
 asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data)
 {
-       return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type), 
-                        (unsigned long)new_flags, (void *)A(data));
+       unsigned long type_page;
+       int err, is_smb, is_ncp;
+
+       if(!suser())
+               return -EPERM;
+       is_smb = is_ncp = 0;
+       err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page);
+       if(err)
+               return err;
+       if(type_page) {
+               is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+               is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+       }
+       if(!is_smb && !is_ncp) {
+               if(type_page)
+                       free_page(type_page);
+               return sys_mount((char *)A(dev_name), (char *)A(dir_name),
+                                (char *)A(type), (unsigned long)new_flags,
+                                (void *)A(data));
+       } else {
+               unsigned long dev_page, dir_page, data_page;
+               int old_fs;
+
+               err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page);
+               if(err)
+                       goto out;
+               err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page);
+               if(err)
+                       goto dev_out;
+               err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page);
+               if(err)
+                       goto dir_out;
+               if(is_ncp)
+                       do_ncp_super_data_conv((void *)data_page);
+               else if(is_smb)
+                       do_smb_super_data_conv((void *)data_page);
+               else
+                       panic("Tell DaveM he fucked up...");
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               err = sys_mount((char *)dev_page, (char *)dir_page,
+                               (char *)type_page, (unsigned long)new_flags,
+                               (void *)data_page);
+               set_fs(old_fs);
+
+               if(data_page)
+                       free_page(data_page);
+       dir_out:
+               if(dir_page)
+                       free_page(dir_page);
+       dev_out:
+               if(dev_page)
+                       free_page(dev_page);
+       out:
+               if(type_page)
+                       free_page(type_page);
+               return err;
+       }
 }
 
 extern asmlinkage int sys_syslog(int type, char * bug, int count);
@@ -1598,6 +1747,31 @@ asmlinkage int sys32_acct(u32 name)
        return sys_acct((const char *)A(name));
 }
 
+extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
+
+asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
+{
+       uid_t sruid, seuid;
+
+       sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+       seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+       return sys_setreuid(sruid, seuid);
+}
+
+extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+
+asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid,
+                              __kernel_uid_t32 euid,
+                              __kernel_uid_t32 suid)
+{
+       uid_t sruid, seuid, ssuid;
+
+       sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+       seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+       ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
+       return sys_setresuid(sruid, seuid, ssuid);
+}
+
 extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
 
 asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid)
@@ -1654,7 +1828,7 @@ asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist)
        set_fs (KERNEL_DS);
        ret = sys_getgroups(gidsetsize, gl);
        set_fs (old_fs);
-       if (ret > 0 && ret <= NGROUPS)
+       if (gidsetsize && ret > 0 && ret <= NGROUPS)
                for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32))
                        if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist)))
                                return -EFAULT;
@@ -1716,6 +1890,9 @@ asmlinkage int sys32_setdomainname(u32 name, int len)
        return sys_setdomainname((char *)A(name), len);
 }
 
+#define RLIM_INFINITY32        0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+
 struct rlimit32 {
        s32     rlim_cur;
        s32     rlim_max;
@@ -1733,8 +1910,8 @@ asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim)
        ret = sys_getrlimit(resource, &r);
        set_fs (old_fs);
        if (!ret && (
-           put_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
-           __put_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max))))
+           put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
+           __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max))))
                return -EFAULT;
        return ret;
 }
@@ -1751,6 +1928,10 @@ asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim)
        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);
@@ -2558,66 +2739,3 @@ asmlinkage int sys32_no_modules(void)
 {
        return -ENOSYS;
 }
-
-struct ncp_mount_data32 {
-        int version;
-        unsigned int ncp_fd;
-        __kernel_uid_t32 mounted_uid;
-        __kernel_pid_t32 wdog_pid;
-        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
-        unsigned int time_out;
-        unsigned int retry_count;
-        unsigned int flags;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
-};
-
-void *do_ncp_super_data_conv(void *raw_data)
-{
-       struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
-       struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
-
-       n->dir_mode = n32->dir_mode;
-       n->file_mode = n32->file_mode;
-       n->gid = n32->gid;
-       n->uid = n32->uid;
-       memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
-       n->wdog_pid = n32->wdog_pid;
-       n->mounted_uid = n32->mounted_uid;
-       return raw_data;
-}
-
-struct smb_mount_data32 {
-        int version;
-        unsigned int fd;
-        __kernel_uid_t32 mounted_uid;
-        struct sockaddr_in addr;
-        char server_name[17];
-        char client_name[17];
-        char service[64];
-        char root_path[64];
-        char username[64];
-        char password[64];
-        char domain[64];
-        unsigned short max_xmit;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
-};
-
-void *do_smb_super_data_conv(void *raw_data)
-{
-       struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
-       struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
-
-       s->dir_mode = s32->dir_mode;
-       s->file_mode = s32->file_mode;
-       s->gid = s32->gid;
-       s->uid = s32->uid;
-       memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr)));
-       s->mounted_uid = s32->mounted_uid;
-       return raw_data;
-}
index a74d0ffbdee0af668c8bb89e99e5fe1a3f4ff293..61ed19b468f946177a48bb8cca326187399e515a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.13 1997/06/04 13:05:29 jj Exp $
+/* $Id: systbls.S,v 1.16 1997/06/16 05:37:41 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -30,7 +30,7 @@ sys_call_table32:
 /*50*/ .xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
        .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve
 /*60*/ .xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize
-       .xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+       .xword sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*70*/ .xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect
        .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups
 /*80*/ .xword sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall
@@ -42,7 +42,7 @@ sys_call_table32:
 /*110*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
        .xword sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall
 /*120*/        .xword sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
-       .xword sys_nis_syscall, sys_setreuid, sys_setregid, sys32_rename, sys32_truncate
+       .xword sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate
 /*130*/        .xword sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
        .xword sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall
 /*140*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
@@ -94,18 +94,18 @@ sys_call_table:
 /*80*/ .xword sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
        .xword sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
 /*90*/ .xword sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
-       .xword sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*100*/        .xword sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-       .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*110*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-       .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_nis_syscall
+       .xword sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
+/*100*/        .xword sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind
+       .xword sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*110*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg
+       .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall
 /*120*/        .xword sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
-       .xword sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
-/*130*/        .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-       .xword sys_nis_syscall, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
-/*140*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
+       .xword sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
+/*130*/        .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown
+       .xword sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
+/*140*/        .xword sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
        .xword sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*150*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*150*/        .xword sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
        .xword sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount
 /*160*/        .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall
        .xword sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
@@ -116,7 +116,7 @@ sys_call_table:
 /*190*/        .xword sys_init_module, sys_personality, sys_prof, sys_break, sys_lock
        .xword sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask
 /*200*/        .xword sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall
-       .xword sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+       .xword sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall
 /*210*/        .xword sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
        .xword sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/        .xword sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
new file mode 100644 (file)
index 0000000..685f8c8
--- /dev/null
@@ -0,0 +1,517 @@
+/* $Id: unaligned.c,v 1.1 1997/06/06 10:56:19 jj Exp $
+ * unaligned.c: Unaligned load/store trap handling with special
+ *              cases for the kernel to do them more quickly.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+
+#include <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 &regs->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
index d0f023d1b6cbf5786c4b6f429cb781337b46776b..d3ed456ca2de236a72452f5412fca62e6a673753 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.6 1997/05/18 04:16:49 davem Exp $
+/* $Id: blockops.S,v 1.7 1997/06/14 21:27:55 davem Exp $
  * arch/sparc64/lib/blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -7,6 +7,8 @@
 
 #include <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;       \
@@ -31,9 +33,9 @@
        .text
        .align  4
 
-#if 0
-       .globl          bzero_1page
-bzero_1page:
+#ifdef VIS_BLOCKOPS
+       .globl          __bzero_1page
+__bzero_1page:
        /* %o0 = buf */
        mov             %o0, %o1
        wr              %g0, ASI_BLK_P, %asi
@@ -60,6 +62,36 @@ bzero_1page:
 
        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
index e9462345a3dd8e1d180b344dfce5147a3f86dcda..86adbc0e92af5fc2aa7f62d5e83046e472568642 100644 (file)
 
 #ifdef __KERNEL__
 
-#define FUNC(x)                                                                                        \
-       .globl  x;                                                                                      \
-       .type   x,@function;                                                                            \
-       .align  4;                                                                                      \
+#define FUNC(x)                \
+       .globl  x;              \
+       .type   x,@function;    \
+       .align  4;              \
 x:
 
 #define FASTER_ALIGNED
@@ -36,10 +36,10 @@ x:
 #define FASTER_ALIGNED
 
 #ifdef DEBUG
-#define FUNC(x)                                                                                        \
-       .globl  jj##x##1;                                                                               \
-       .type   jj##x##1,@function;                                                                     \
-       .align  4;                                                                                      \
+#define FUNC(x)                        \
+       .globl  jj##x##1;               \
+       .type   jj##x##1,@function;     \
+       .align  4;                      \
 jj##x##1:
 #else
 #include "DEFS.h"
@@ -51,56 +51,56 @@ jj##x##1:
 
 #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
index 713c78ca8355d6cae0b65196a5fee90d1e3be470..a327316e66b9f628b3f85a008ffa63bbcb221a7c 100644 (file)
@@ -31,7 +31,8 @@
 
 /* Please don't change these macros, unless you change the logic
  * in the .fixup section below as well.
- * Store 64 bytes at (BASE + OFFSET) using value SOURCE. */
+ * Store 64 bytes at (BASE + OFFSET) using value SOURCE.
+ */
 #define ZERO_BIG_BLOCK(base, offset, source)    \
        stxa    source, [base + offset + 0x00] %asi; \
        stxa    source, [base + offset + 0x08] %asi; \
index 6df923a4bf2ffd0195d2419740723744d9d7395c..b8da1997c68685679e92590d75df52786c297041 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.11 1997/06/01 05:46:15 davem Exp $
+/* $Id: fault.c,v 1.12 1997/06/13 14:02:52 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -137,6 +137,13 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
 /* #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)
@@ -151,26 +158,36 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write
        static unsigned long last_addr = 0;
        static int rcnt = 0;
 
+       if(fault_trace_enable) {
 #ifdef FAULT_TRACER_VERBOSE
-       printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...",
-              regs->tpc, text_fault, write, address);
+               printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...",
+                      regs->tpc, text_fault, write, address);
 #else
-       printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write);
+               printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write);
 #endif
-       if(address == last_addr) {
-               if(rcnt++ > 15) {
-                       printk("Wheee lotsa bogus faults, something wrong, spinning\n");
-                       __asm__ __volatile__("flushw");
-                       printk("o7[%016lx] i7[%016lx]\n",
-                              regs->u_regs[UREG_I7],
-                   ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]);
-                       sti();
-                       while(1)
-                               barrier();
-               }
-       } else rcnt = 0;
-       last_addr = address;
+               if(address == last_addr) {
+                       if(rcnt++ > 15) {
+                               printk("Wheee lotsa bogus faults, something wrong, "
+                                      "spinning\n");
+                               printk("pctx[%016lx]sctx[%016lx]mmctx[%016lx]DS(%x)"
+                                      "tctx[%016lx] flgs[%016lx]\n",
+                                      spitfire_get_primary_context(),
+                                      spitfire_get_secondary_context(),
+                                      mm->context, (unsigned)current->tss.current_ds,
+                                      current->tss.ctx, current->tss.flags);
+                               __asm__ __volatile__("flushw");
+                               printk("o7[%016lx] i7[%016lx]\n",
+                                      regs->u_regs[UREG_I7],
+                     ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]);
+                               sti();
+                               while(1)
+                                       barrier();
+                       }
+               } else rcnt = 0;
+               last_addr = address;
+       }
 #endif
+
        lock_kernel ();
        down(&mm->mmap_sem);
        vma = find_vma(mm, address);
@@ -233,11 +250,13 @@ bad_area:
 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
 }
 
index 960b3cbbd7fd761b72e0ceb9df6b3ded12112b91..a43820257120708fa56fc3e4ba08c65bc528926c 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.29 1997/05/27 06:28:13 davem Exp $
+/*  $Id: init.c,v 1.30 1997/06/06 10:56:21 jj Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -440,9 +440,9 @@ void sparc_ultra_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
        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);
 }
index b0f3e03da74b404fec069192c99244d24b32a7f5..61b792f74ca5734ba3a6c4ad9840b3ec1306db25 100644 (file)
@@ -2602,8 +2602,8 @@ __initfunc(static void probe_for_hwifs (void))
                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 */
index 6a00095110aeeb30440dc5c42ff253fe27911c77..3083c0c543f0b3ea5e4f73be0cf9a7b8fda54748 100644 (file)
@@ -1,3 +1,27 @@
+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
index 3c1e7f27634ca347aadc5943e3f6d7e881fadc08..51f7296b1f125408b122503ba0abd973b6518f14 100644 (file)
@@ -497,13 +497,15 @@ static void set_origin(int currcons)
        __set_origin(__real_origin);
 }
 
-static void scrup(int currcons, unsigned int t, unsigned int b)
+static void scrup(int currcons, unsigned int t, unsigned int b, unsigned int nr)
 {
        int hardscroll = hardscroll_enabled;
 
-       if (b > video_num_lines || t >= b)
+       if (t+nr >= b)
+               nr = b - t - 1;
+       if (b > video_num_lines || t >= b || nr < 1)
                return;
-       if (t || b != video_num_lines)
+       if (t || b != video_num_lines || nr > 1)
                hardscroll = 0;
        if (hardscroll) {
                origin += video_size_row;
@@ -544,31 +546,35 @@ static void scrup(int currcons, unsigned int t, unsigned int b)
                set_origin(currcons);
        } else {
                unsigned short * d = (unsigned short *) (origin+video_size_row*t);
-               unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1));
+               unsigned short * s = (unsigned short *) (origin+video_size_row*(t+nr));
 
-               memcpyw(d, s, (b-t-1) * video_size_row);
-               memsetw(d + (b-t-1) * video_num_columns, video_erase_char, video_size_row);
+               memcpyw(d, s, (b-t-nr) * video_size_row);
+               memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
        }
 }
 
 static void
-scrdown(int currcons, unsigned int t, unsigned int b)
+scrdown(int currcons, unsigned int t, unsigned int b, unsigned int nr)
 {
        unsigned short *s;
        unsigned int count;
+       unsigned int step;
 
-       if (b > video_num_lines || t >= b)
+       if (t+nr >= b)
+               nr = b - t - 1;
+       if (b > video_num_lines || t >= b || nr < 1)
                return;
-       s = (unsigned short *) (origin+video_size_row*(b-2));
-       if (b >= t + 1) {
-               count = b - t - 1;
-               while (count) {
-                       count--;
-                       memcpyw(s + video_num_columns, s, video_size_row);
-                       s -= video_num_columns;
-               }
+       s = (unsigned short *) (origin+video_size_row*(b-nr-1));
+       step = video_num_columns * nr;
+       count = b - t - nr;
+       while (count--) {
+               memcpyw(s + step, s, video_size_row);
+               s -= video_num_columns;
+       }
+       while (nr--) {
+               s += video_num_columns;
+               memsetw(s, video_erase_char, video_size_row);
        }
-       memsetw(s + video_num_columns, video_erase_char, video_size_row);
        has_scrolled = 1;
 }
 
@@ -578,7 +584,7 @@ static void lf(int currcons)
         * if below scrolling region
         */
        if (y+1 == bottom)
-               scrup(currcons,top,bottom);
+               scrup(currcons,top,bottom, 1);
        else if (y < video_num_lines-1) {
                y++;
                pos += video_size_row;
@@ -592,7 +598,7 @@ static void ri(int currcons)
         * if above scrolling region
         */
        if (y == top)
-               scrdown(currcons,top,bottom);
+               scrdown(currcons,top,bottom,1);
        else if (y > 0) {
                y--;
                pos -= video_size_row;
@@ -1117,9 +1123,9 @@ static void insert_char(int currcons)
        need_wrap = 0;
 }
 
-static void insert_line(int currcons)
+static void insert_line(int currcons, unsigned int nr)
 {
-       scrdown(currcons,y,bottom);
+       scrdown(currcons,y,bottom,nr);
        need_wrap = 0;
 }
 
@@ -1136,9 +1142,9 @@ static void delete_char(int currcons)
        need_wrap = 0;
 }
 
-static void delete_line(int currcons)
+static void delete_line(int currcons, unsigned int nr)
 {
-       scrup(currcons,y,bottom);
+       scrup(currcons,y,bottom,nr);
        need_wrap = 0;
 }
 
@@ -1158,8 +1164,7 @@ static void csi_L(int currcons, unsigned int nr)
                nr = video_num_lines;
        else if (!nr)
                nr = 1;
-       while (nr--)
-               insert_line(currcons);
+       insert_line(currcons, nr);
 }
 
 static void csi_P(int currcons, unsigned int nr)
@@ -1178,8 +1183,7 @@ static void csi_M(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)
index 8db4e14433bf738080bc92ca7872c247f1bc948f..a5f37f507758081e6d628ac91cf4df46f5fe481d 100644 (file)
@@ -88,9 +88,17 @@ void n_tty_flush_buffer(struct tty_struct * tty)
 
 /*
  * Return number of characters buffered to be delivered to user
+ * 
  */
 int n_tty_chars_in_buffer(struct tty_struct *tty)
 {
+       if (tty->icanon) {
+               if (!tty->canon_data) return 0;
+
+               return (tty->canon_head > tty->read_tail) ?
+                       tty->canon_head - tty->read_tail :
+                       tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+       }
        return tty->read_cnt;
 }
 
@@ -157,6 +165,72 @@ static int opost(unsigned char c, struct tty_struct *tty)
        return 0;
 }
 
+/*
+ * opost_block --- to speed up block console writes, among other
+ * things.
+ */
+static int opost_block(struct tty_struct * tty,
+                      const unsigned char * inbuf, unsigned int nr)
+{
+       char    buf[80];
+       int     space;
+       int     i;
+       char    *cp;
+
+       space = tty->driver.write_room(tty);
+       if (!space)
+               return 0;
+       if (nr > space)
+               nr = space;
+       if (nr > sizeof(buf))
+           nr = sizeof(buf);
+       nr -= copy_from_user(buf, inbuf, nr);
+       if (!nr)
+               return 0;
+       
+       for (i = 0, cp = buf; i < nr; i++, cp++) {
+               switch (*cp) {
+               case '\n':
+                       if (O_ONLRET(tty))
+                               tty->column = 0;
+                       if (O_ONLCR(tty))
+                               goto break_out;
+                       tty->canon_column = tty->column;
+                       break;
+               case '\r':
+                       if (O_ONOCR(tty) && tty->column == 0)
+                               goto break_out;
+                       if (O_OCRNL(tty)) {
+                               *cp = '\n';
+                               if (O_ONLRET(tty))
+                                       tty->canon_column = tty->column = 0;
+                               break;
+                       }
+                       tty->canon_column = tty->column = 0;
+                       break;
+               case '\t':
+                       goto break_out;
+               case '\b':
+                       if (tty->column > 0)
+                               tty->column--;
+                       break;
+               default:
+                       if (O_OLCUC(tty))
+                               *cp = toupper(*cp);
+                       if (!iscntrl(*cp))
+                               tty->column++;
+                       break;
+               }
+       }
+break_out:
+       if (tty->driver.flush_chars)
+               tty->driver.flush_chars(tty);
+       i = tty->driver.write(tty, 0, buf, i);  
+       return i;
+}
+
+
+
 static inline void put_char(unsigned char c, struct tty_struct *tty)
 {
        tty->driver.put_char(tty, c);
@@ -934,7 +1008,7 @@ static int write_chan(struct tty_struct * tty, struct file * file,
                      const unsigned char * buf, unsigned int nr)
 {
        struct wait_queue wait = { current, NULL };
-       int c;
+       int c, num;
        const unsigned char *b = buf;
        int retval = 0;
 
@@ -958,6 +1032,11 @@ static int write_chan(struct tty_struct * tty, struct file * file,
                }
                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;
index 5f76193915b6ef4517f68b9f3ae20202eb12248b..2e905fadd66344761074d4c8a4aafb6004d2ad37 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 1.02, last modified 15-Apr-97
+ * Version 1.03, last modified 26-Apr-97
  * 
  * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997.  All rights reserved.
  *
@@ -1335,11 +1335,15 @@ struct file_operations urandom_fops = {
  * starting point for each pair of TCP endpoints.  This defeats
  * attacks which rely on guessing the initial TCP sequence number.
  * This algorithm was suggested by Steve Bellovin.
+ *
+ * Using a very strong hash was taking an appreciable amount of the total
+ * TCP connection establishment time, so this is a weaker hash,
+ * compensated for by changing the secret periodically.
  */
 
 /* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
 #define H(x, y, z) ((x) ^ (y) ^ (z))
 
 #define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
@@ -1357,9 +1361,9 @@ struct file_operations urandom_fops = {
    (a) = ROTL ((s), (a));}
 
 /*
- * Basic cut-down MD4 transform
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
  */
-static void halfMD4Transform (__u32 buf[4], __u32 in[8])
+static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
 {
        __u32   a = buf[0], b = buf[1], c = buf[2], d = buf[3];
 
@@ -1376,77 +1380,141 @@ static void halfMD4Transform (__u32 buf[4], __u32 in[8])
        /* 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
 /*
index e2d6aebc5d5bb657c695a96eec311e86946bf170..2e39b2fef9bf7d7091efbe8293a82d3c95e40504 100644 (file)
@@ -1328,6 +1328,9 @@ static void shutdown(struct async_struct * info)
        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);
@@ -1995,6 +1998,30 @@ static void send_break(  struct async_struct * info, int duration)
 #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.
@@ -2199,6 +2226,19 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        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:
index c08e44a275ecff4edf0965f2c9f597e3915fa4b5..7678e75e9af502f1821fa6fa0aff9b255eda4944 100644 (file)
  * 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>
@@ -90,8 +93,8 @@
 
 #undef TTY_DEBUG_HANGUP
 
-#define TTY_PARANOIA_CHECK
-#define CHECK_TTY_COUNT
+#define TTY_PARANOIA_CHECK 1
+#define CHECK_TTY_COUNT 1
 
 struct termios tty_std_termios;                /* for the benefit of tty drivers  */
 struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */
@@ -651,18 +654,31 @@ static long tty_write(struct inode * inode, struct file * file,
                (unsigned int)count);
 }
 
+/* Semaphore to protect creating and releasing a tty */
+static struct semaphore tty_sem = MUTEX;
+static void down_tty_sem(int index)
+{
+       down(&tty_sem);
+}
+static void up_tty_sem(int index)
+{
+       up(&tty_sem);
+}
+static void release_mem(struct tty_struct *tty, int idx);
+
 /*
- * This is so ripe with races that you should *really* not touch this
- * unless you know exactly what you are doing. All the changes have to be
- * made atomically, or there may be incorrect pointers all over the place.
+ * WSH 06/09/97: Rewritten to remove races and properly clean up after a
+ * failed open.  The new code protects the open with a semaphore, so it's
+ * really quite straightforward.  The semaphore locking can probably be
+ * relaxed for the (most common) case of reopening a tty.
  */
 static int init_dev(kdev_t device, struct tty_struct **ret_tty)
 {
-       struct tty_struct *tty, **tty_loc, *o_tty, **o_tty_loc;
+       struct tty_struct *tty, *o_tty;
        struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
        struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
        struct tty_driver *driver;      
-       int retval;
+       int retval=0;
        int idx;
 
        driver = get_tty_driver(device);
@@ -670,175 +686,236 @@ static int init_dev(kdev_t device, struct tty_struct **ret_tty)
                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;
@@ -849,10 +926,11 @@ static void release_dev(struct file * filp)
 
        tty_fasync(filp->f_inode, filp, 0);
 
-       tp = tty->termios;
-       ltp = tty->termios_locked;
-
        idx = MINOR(tty->device) - tty->driver.minor_start;
+       pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
+                     tty->driver.subtype == PTY_TYPE_MASTER);
+       o_tty = tty->link;
+
 #ifdef TTY_PARANOIA_CHECK
        if (idx < 0 || idx >= tty->driver.num) {
                printk("release_dev: bad idx when trying to free (%s)\n",
@@ -864,15 +942,15 @@ static void release_dev(struct file * filp)
                       idx, kdevname(tty->device));
                return;
        }
-       if (tp != tty->driver.termios[idx]) {
-               printk("release_dev: driver.termios[%d] not termios for ("
-                      "%s)\n",
+       if (tty->termios != tty->driver.termios[idx]) {
+               printk("release_dev: driver.termios[%d] not termios "
+                      "for (%s)\n",
                       idx, kdevname(tty->device));
                return;
        }
-       if (ltp != tty->driver.termios_locked[idx]) {
-               printk("release_dev: driver.termios_locked[%d] not termios_locked for ("
-                      "%s)\n",
+       if (tty->termios_locked != tty->driver.termios_locked[idx]) {
+               printk("release_dev: driver.termios_locked[%d] not "
+                      "termios_locked for (%s)\n",
                       idx, kdevname(tty->device));
                return;
        }
@@ -883,10 +961,6 @@ static void release_dev(struct file * filp)
               tty->count);
 #endif
 
-       o_tty = tty->link;
-       o_tp = (o_tty) ? o_tty->termios : NULL;
-       o_ltp = (o_tty) ? o_tty->termios_locked : NULL;
-
 #ifdef TTY_PARANOIA_CHECK
        if (tty->driver.other) {
                if (o_tty != tty->driver.other->table[idx]) {
@@ -895,34 +969,90 @@ static void release_dev(struct file * filp)
                               idx, kdevname(tty->device));
                        return;
                }
-               if (o_tp != tty->driver.other->termios[idx]) {
-                       printk("release_dev: other->termios[%d] not o_termios for ("
-                              "%s)\n",
+               if (o_tty->termios != tty->driver.other->termios[idx]) {
+                       printk("release_dev: other->termios[%d] not o_termios "
+                              "for (%s)\n",
                               idx, kdevname(tty->device));
                        return;
                }
-               if (o_ltp != tty->driver.other->termios_locked[idx]) {
-                       printk("release_dev: other->termios_locked[%d] not o_termios_locked for ("
-                              "%s)\n",
+               if (o_tty->termios_locked != 
+                     tty->driver.other->termios_locked[idx]) {
+                       printk("release_dev: other->termios_locked[%d] not "
+                              "o_termios_locked for (%s)\n",
                               idx, kdevname(tty->device));
                        return;
                }
-
                if (o_tty->link != tty) {
                        printk("release_dev: bad pty pointers\n");
                        return;
                }
        }
 #endif
-       
+       /*
+        * Sanity check: if tty->count is going to zero, there shouldn't be
+        * any waiters on tty->read_wait or tty->write_wait.  We test the
+        * wait queues and kick everyone out _before_ actually starting to
+        * close.  This ensures that we won't block while releasing the tty
+        * structure.
+        *
+        * The test for the o_tty closing is necessary, since the master and
+        * slave sides may close in any order.  If the slave side closes out
+        * first, its count will be one, since the master side holds an open.
+        * Thus this test wouldn't be triggered at the time the slave closes,
+        * so we do it now.
+        *
+        * Note that it's possible for the tty to be opened again while we're
+        * flushing out waiters.  By recalculating the closing flags before
+        * each iteration we avoid any problems.
+        */
+       while (1) {
+               tty_closing = tty->count <= 1;
+               o_tty_closing = o_tty &&
+                       (o_tty->count <= (pty_master ? 1 : 0));
+               do_sleep = 0;
+
+               if (tty_closing) {
+                       if (waitqueue_active(&tty->read_wait)) {
+                               wake_up(&tty->read_wait);
+                               do_sleep++;
+                       }
+                       if (waitqueue_active(&tty->write_wait)) {
+                               wake_up(&tty->write_wait);
+                               do_sleep++;
+                       }
+               }
+               if (o_tty_closing) {
+                       if (waitqueue_active(&o_tty->read_wait)) {
+                               wake_up(&o_tty->read_wait);
+                               do_sleep++;
+                       }
+                       if (waitqueue_active(&o_tty->write_wait)) {
+                               wake_up(&o_tty->write_wait);
+                               do_sleep++;
+                       }
+               }
+               if (!do_sleep)
+                       break;
+
+               printk("release_dev: %s: read/write wait queue active!\n",
+                      tty_name(tty));
+               schedule();
+       }       
+
+       /*
+        * The closing flags are now consistent with the open counts on 
+        * both sides, and we've completed the last operation that could 
+        * block, so it's safe to proceed with closing.
+        */
+
        if (tty->driver.close)
                tty->driver.close(tty, filp);
-       if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
-           tty->driver.subtype == PTY_TYPE_MASTER) {
-               if (--tty->link->count < 0) {
+
+       if (pty_master) {
+               if (--o_tty->count < 0) {
                        printk("release_dev: bad pty slave count (%d) for %s\n",
-                              tty->count, tty_name(tty));
-                       tty->link->count = 0;
+                              o_tty->count, tty_name(o_tty));
+                       o_tty->count = 0;
                }
        }
        if (--tty->count < 0) {
@@ -930,60 +1060,50 @@ static void release_dev(struct file * filp)
                       tty->count, tty_name(tty));
                tty->count = 0;
        }
-       if (tty->count)
-               return;
 
        /*
-        * Sanity check --- if tty->count is zero, there shouldn't be
-        * any waiters on tty->read_wait or tty->write_wait.  But just
-        * in case....
+        * Perform some housekeeping before deciding whether to return.
+        *
+        * Set the TTY_CLOSING flag if this was the last open.  In the
+        * case of a pty we may have to wait around for the other side
+        * to close, and TTY_CLOSING makes sure we can't be reopened.
         */
-       while (1) {
-               if (waitqueue_active(&tty->read_wait)) {
-                       printk("release_dev: %s: read_wait active?!?\n",
-                              tty_name(tty));
-                       wake_up(&tty->read_wait);
-               } else if (waitqueue_active(&tty->write_wait)) {
-                       printk("release_dev: %s: write_wait active?!?\n",
-                              tty_name(tty));
-                       wake_up(&tty->write_wait);
-               } else
-                       break;
-               schedule();
-       }
-       
+       if(tty_closing)
+               tty->flags |= (1 << TTY_CLOSING);
+       if(o_tty_closing)
+               o_tty->flags |= (1 << TTY_CLOSING);
+
        /*
-        * We're committed; at this point, we must not block!
+        * If _either_ side is closing, make sure there aren't any
+        * processes that still think tty or o_tty is their controlling
+        * tty.  Also, clear redirect if it points to either tty.
         */
-       if (o_tty) {
-               if (o_tty->count)
-                       return;
-               tty->driver.other->table[idx] = NULL;
-               tty->driver.other->termios[idx] = NULL;
-               kfree_s(o_tp, sizeof(struct termios));
+       if (tty_closing || o_tty_closing) {
+               struct task_struct *p;
+
+               read_lock(&tasklist_lock);
+               for_each_task(p) {
+                       if (p->tty == tty || (o_tty && p->tty == o_tty))
+                               p->tty = NULL;
+               }
+               read_unlock(&tasklist_lock);
+
+               if (redirect == tty || (o_tty && redirect == o_tty))
+                       redirect = NULL;
        }
+
+       /* check whether both sides are closing ... */
+       if (!tty_closing || (o_tty && !o_tty_closing))
+               return;
+       filp->private_data = 0;
        
 #ifdef TTY_DEBUG_HANGUP
        printk("freeing tty structure...");
 #endif
-       tty->flags |= (1 << TTY_CLOSING);
 
        /*
-        * Make sure there aren't any processes that still think this
-        * tty is their controlling tty.
-        */
-       read_lock(&tasklist_lock);
-       for_each_task(p) {
-               if (p->tty == tty)
-                       p->tty = NULL;
-               if (o_tty && p->tty == o_tty)
-                       p->tty = NULL;
-       }
-       read_unlock(&tasklist_lock);
-
-       /*
-        * Shutdown the current line discipline, and reset it to
-        * N_TTY.
+        * Shutdown the current line discipline, and reset it to N_TTY.
+        * N.B. why reset ldisc when we're releasing the memory??
         */
        if (tty->ldisc.close)
                (tty->ldisc.close)(tty);
@@ -995,41 +1115,34 @@ static void release_dev(struct file * filp)
                o_tty->ldisc = ldiscs[N_TTY];
        }
        
-       tty->driver.table[idx] = NULL;
-       if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
-               tty->driver.termios[idx] = NULL;
-               kfree_s(tp, sizeof(struct termios));
-       }
-       if (tty == redirect || o_tty == redirect)
-               redirect = NULL;
        /*
         * Make sure that the tty's task queue isn't activated.  If it
-        * is, take it out of the linked list.
+        * is, take it out of the linked list.  The tqueue isn't used by
+        * pty's, so skip the test for them.
         */
-       spin_lock_irq(&tqueue_lock);
-       if (tty->flip.tqueue.sync) {
-               struct tq_struct *tq, *prev;
-
-               for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
-                       if (tq == &tty->flip.tqueue) {
-                               if (prev)
-                                       prev->next = tq->next;
-                               else
-                                       tq_timer = tq->next;
-                               break;
+       if (tty->driver.type != TTY_DRIVER_TYPE_PTY) {
+               spin_lock_irq(&tqueue_lock);
+               if (tty->flip.tqueue.sync) {
+                       struct tq_struct *tq, *prev;
+
+                       for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
+                               if (tq == &tty->flip.tqueue) {
+                                       if (prev)
+                                               prev->next = tq->next;
+                                       else
+                                               tq_timer = tq->next;
+                                       break;
+                               }
                        }
                }
+               spin_unlock_irq(&tqueue_lock);
        }
-       spin_unlock_irq(&tqueue_lock);
-       tty->magic = 0;
-       (*tty->driver.refcount)--;
-       free_page((unsigned long) tty);
-       filp->private_data = 0;
-       if (o_tty) {
-               o_tty->magic = 0;
-               (*o_tty->driver.refcount)--;
-               free_page((unsigned long) o_tty);
-       }
+
+       /* 
+        * The release_mem function takes care of the details of clearing
+        * the slots and preserving the termios structure.
+        */
+       release_mem(tty, idx);
 }
 
 /*
@@ -1077,6 +1190,7 @@ retry_open:
        retval = init_dev(device, &tty);
        if (retval)
                return retval;
+       /* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */
        filp->private_data = tty;
        check_tty_count(tty, "tty_open");
        if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
@@ -1123,11 +1237,6 @@ retry_open:
        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);
index 5af3d2e6c5305322e62bdd509a894aa6acf7f5d7..ff87210b87d19b9ef1f4830ae5bf8297bed93283 100644 (file)
@@ -1,5 +1,5 @@
 #
-#  $Id: Makefile,v 1.3 1997/05/27 23:25:01 fritz Exp $
+#  $Id: Makefile,v 1.1 1997/03/22 02:01:22 fritz Exp $
 #  Copyright (C) 1996  SpellCaster Telecommunications Inc.
 #
 #  This program is free software; you can redistribute it and/or modify
index a699a4be26a0efe5762c66b94066e04e187905d4..1cc7b5bae850bbc12029ff68dbcb822b797061df 100644 (file)
@@ -15,6 +15,9 @@ tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
 #
 bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
 if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+  if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then
+    bool 'MIPS JAZZ onboard SONIC ethernet support' CONFIG_MIPS_JAZZ_SONIC
+  fi
   bool '3COM cards' CONFIG_NET_VENDOR_3COM
   if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
     tristate '3c501 support' CONFIG_EL1
@@ -110,7 +113,12 @@ fi
 #
 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
 
index 901e821af164775f442fb32de268fab756ed363d..bc9a0721746f800bce48a2fb740172580f5b4bc2 100644 (file)
@@ -275,6 +275,10 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SGISEEQ), y)
+L_OBJS += sgiseeq.o
+endif
+
 ifeq ($(CONFIG_HAPPYMEAL),y)
 L_OBJS += sunhme.o
 else
@@ -563,6 +567,14 @@ 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
@@ -651,6 +663,14 @@ 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
index aacec03fb870ed7c7c34e0401bc6509dfb339439..b1289ed76ff271a57e368f49bbf206eb86e26a87 100644 (file)
@@ -74,6 +74,7 @@ extern int es_probe(struct device *);
 extern int e2100_probe(struct device *);
 extern int ni52_probe(struct device *);
 extern int ni65_probe(struct device *);
+extern int sonic_probe(struct device *);
 extern int SK_init(struct device *);
 extern int seeq8005_probe(struct device *);
 extern int tc59x_probe(struct device *);
@@ -83,6 +84,7 @@ extern int sparc_lance_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 *);
@@ -241,7 +243,7 @@ __initfunc(static int ethif_probe(struct device *dev))
        && sparc_lance_probe(dev)
 #endif
 #ifdef CONFIG_HAPPYMEAL
-        && happy_meal_probe(dev)
+       && happy_meal_probe(dev)
 #endif
 #ifdef CONFIG_SUNQE
        && qec_probe(dev)
@@ -249,6 +251,12 @@ __initfunc(static int ethif_probe(struct device *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. */
     }
@@ -293,6 +301,17 @@ static struct device atp_dev = {
 #   define NEXT_DEV    (&dev_ltpc)
 #endif  /* LTPC */
 
+#if defined(CONFIG_COPS)
+    extern int cops_probe(struct device *);
+    static struct device dev_cops = {
+        "lt0",
+        0, 0, 0, 0,
+        0x0, 0,
+        0, 0, 0, NEXT_DEV, cops_probe };
+#   undef NEXT_DEV
+#   define NEXT_DEV     (&dev_cops)
+#endif  /* COPS */
+
 /* The first device defaults to I/O base '0', which means autoprobe. */
 #ifndef ETH0_ADDR
 # define ETH0_ADDR 0
diff --git a/drivers/net/cops.c b/drivers/net/cops.c
new file mode 100644 (file)
index 0000000..a7e7c13
--- /dev/null
@@ -0,0 +1,1016 @@
+/*      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 */
diff --git a/drivers/net/cops.h b/drivers/net/cops.h
new file mode 100644 (file)
index 0000000..a064bc1
--- /dev/null
@@ -0,0 +1,60 @@
+/*      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
diff --git a/drivers/net/cops_ffdrv.h b/drivers/net/cops_ffdrv.h
new file mode 100644 (file)
index 0000000..12a488c
--- /dev/null
@@ -0,0 +1,532 @@
+
+/*
+ *     The firmware this driver downloads into the Localtalk card is a
+ *     seperate program and is not GPL'd source code, even though the Linux
+ *     side driver and the routine that loads this data into the card are.
+ *     
+ *     It is taken from the COPS SDK and is under the following license
+ *
+ *     This material is licensed to you strictly for use in conjunction with
+ *     the use of COPS LocalTalk adapters.
+ *     There is no charge for this SDK. And no waranty express or implied
+ *     about its fitness for any purpose. However, we will cheerefully
+ *     refund every penny you paid for this SDK...
+ *     Regards,
+ *
+ *     Thomas F. Divine
+ *     Chief Scientist
+ */
+
+
+/*      cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
+ *
+ *      Authors:
+ *      - Jay Schulist <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
diff --git a/drivers/net/cops_ltdrv.h b/drivers/net/cops_ltdrv.h
new file mode 100644 (file)
index 0000000..6ec3340
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *     The firmware this driver downloads into the Localtalk card is a
+ *     seperate program and is not GPL'd source code, even though the Linux
+ *     side driver and the routine that loads this data into the card are.
+ *     
+ *     It is taken from the COPS SDK and is under the following license
+ *
+ *     This material is licensed to you strictly for use in conjunction with
+ *     the use of COPS LocalTalk adapters.
+ *     There is no charge for this SDK. And no waranty express or implied
+ *     about its fitness for any purpose. However, we will cheerefully
+ *     refund every penny you paid for this SDK...
+ *     Regards,
+ *
+ *     Thomas F. Divine
+ *     Chief Scientist
+ */
+
+
+/*      cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
+ *
+ *      Authors:
+ *      - Jay Schulist <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
index e282847a9c9c1513af9cae1117cc8d88c9aac4d7..5f8cb5cca942b4aaa8b5e33b1010a5e718fae865 100644 (file)
@@ -407,7 +407,7 @@ static int lapbeth_close(struct device *dev)
        return 0;
 }
 
-__initfunc(static int lapbeth_dev_init(struct device *dev))
+static int lapbeth_dev_init(struct device *dev)
 {
        return 0;
 }
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
new file mode 100644 (file)
index 0000000..6ee6a83
--- /dev/null
@@ -0,0 +1,737 @@
+/* $Id: sgiseeq.c,v 1.1 1997/06/09 08:34:30 ralf Exp $
+ * sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <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);
+
+}
diff --git a/drivers/net/sgiseeq.h b/drivers/net/sgiseeq.h
new file mode 100644 (file)
index 0000000..4f684f5
--- /dev/null
@@ -0,0 +1,103 @@
+/* $Id: sgiseeq.h,v 1.1 1997/06/09 08:34:32 ralf Exp $
+ * sgiseeq.h: Defines for the Seeq8003 ethernet controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _SGISEEQ_H
+#define _SGISEEQ_H
+
+struct sgiseeq_wregs {
+       volatile unsigned long multicase_high[2];
+       volatile unsigned long frame_gap;
+       volatile unsigned long control;
+};
+
+struct sgiseeq_rregs {
+       volatile unsigned long collision_tx[2];
+       volatile unsigned long collision_all[2];
+       volatile unsigned long _unused0;
+       volatile unsigned long rflags; 
+};
+
+struct sgiseeq_regs {
+       union {
+               volatile unsigned long eth_addr[6];
+               volatile unsigned long multicast_low[6];
+               struct sgiseeq_wregs wregs;
+               struct sgiseeq_rregs rregs;
+       } rw;
+       volatile unsigned long rstat;
+       volatile unsigned long tstat;
+};
+
+/* Seeq8003 receive status register */
+#define SEEQ_RSTAT_OVERF   0x001 /* Overflow */
+#define SEEQ_RSTAT_CERROR  0x002 /* CRC error */
+#define SEEQ_RSTAT_DERROR  0x004 /* Dribble error */
+#define SEEQ_RSTAT_SFRAME  0x008 /* Short frame */
+#define SEEQ_RSTAT_REOF    0x010 /* Received end of frame */
+#define SEEQ_RSTAT_FIG     0x020 /* Frame is good */
+#define SEEQ_RSTAT_TIMEO   0x040 /* Timeout, or late receive */
+#define SEEQ_RSTAT_WHICH   0x080 /* Which status, 1=old 0=new */
+#define SEEQ_RSTAT_LITTLE  0x100 /* DMA is done in little endian format */
+#define SEEQ_RSTAT_SDMA    0x200 /* DMA has started */
+#define SEEQ_RSTAT_ADMA    0x400 /* DMA is active */
+#define SEEQ_RSTAT_ROVERF  0x800 /* Receive buffer overflow */
+
+/* Seeq8003 receive command register */
+#define SEEQ_RCMD_RDISAB   0x000 /* Disable receiver on the Seeq8003 */
+#define SEEQ_RCMD_IOVERF   0x001 /* IRQ on buffer overflows */
+#define SEEQ_RCMD_ICRC     0x002 /* IRQ on CRC errors */
+#define SEEQ_RCMD_IDRIB    0x004 /* IRQ on dribble errors */
+#define SEEQ_RCMD_ISHORT   0x008 /* IRQ on short frames */
+#define SEEQ_RCMD_IEOF     0x010 /* IRQ on end of frame */
+#define SEEQ_RCMD_IGOOD    0x020 /* IRQ on good frames */
+#define SEEQ_RCMD_RANY     0x040 /* Receive any frame */
+#define SEEQ_RCMD_RBCAST   0x080 /* Receive broadcasts */
+#define SEEQ_RCMD_RBMCAST  0x0c0 /* Receive broadcasts/multicasts */
+
+/* Seeq8003 transmit status register */
+#define SEEQ_TSTAT_UFLOW   0x001 /* Transmit buffer underflow */
+#define SEEQ_TSTAT_CLS     0x002 /* Collision detected */
+#define SEEQ_TSTAT_R16     0x004 /* Did 16 retries to tx a frame */
+#define SEEQ_TSTAT_PTRANS  0x008 /* Packet was transmitted ok */
+#define SEEQ_TSTAT_LCLS    0x010 /* Late collision occurred */
+#define SEEQ_TSTAT_WHICH   0x080 /* Which status, 1=old 0=new */
+#define SEEQ_TSTAT_TLE     0x100 /* DMA is done in little endian format */
+#define SEEQ_TSTAT_SDMA    0x200 /* DMA has started */
+#define SEEQ_TSTAT_ADMA    0x400 /* DMA is active */
+
+/* Seeq8003 transmit command register */
+#define SEEQ_TCMD_RB0      0x00 /* Register bank zero w/station addr */
+#define SEEQ_TCMD_IUF      0x01 /* IRQ on tx underflow */
+#define SEEQ_TCMD_IC       0x02 /* IRQ on collisions */
+#define SEEQ_TCMD_I16      0x04 /* IRQ after 16 failed attempts to tx frame */
+#define SEEQ_TCMD_IPT      0x08 /* IRQ when packet successfully transmitted */
+#define SEEQ_TCMD_RB1      0x20 /* Register bank one w/multi-cast low byte */ 
+#define SEEQ_TCMD_RB2      0x40 /* Register bank two w/multi-cast high byte */
+
+/* Seeq8003 control register */
+#define SEEQ_CTRL_XCNT     0x01
+#define SEEQ_CTRL_ACCNT    0x02
+#define SEEQ_CTRL_SFLAG    0x04
+#define SEEQ_CTRL_EMULTI   0x08
+#define SEEQ_CTRL_ESHORT   0x10
+#define SEEQ_CTRL_ENCARR   0x20
+
+/* Seeq8003 control registers on the SGI Hollywood HPC. */
+#define SEEQ_HPIO_P1BITS  0x00000001 /* cycles to stay in P1 phase for PIO */
+#define SEEQ_HPIO_P2BITS  0x00000060 /* cycles to stay in P2 phase for PIO */
+#define SEEQ_HPIO_P3BITS  0x00000100 /* cycles to stay in P3 phase for PIO */
+#define SEEQ_HDMA_D1BITS  0x00000006 /* cycles to stay in D1 phase for DMA */
+#define SEEQ_HDMA_D2BITS  0x00000020 /* cycles to stay in D2 phase for DMA */
+#define SEEQ_HDMA_D3BITS  0x00000000 /* cycles to stay in D3 phase for DMA */
+#define SEEQ_HDMA_TIMEO   0x00030000 /* cycles for DMA timeout */
+#define SEEQ_HCTL_NORM    0x00000000 /* Normal operation mode */
+#define SEEQ_HCTL_RESET   0x00000001 /* Reset Seeq8003 and HPC interface */
+#define SEEQ_HCTL_IPEND   0x00000002 /* IRQ is pending for the chip */
+#define SEEQ_HCTL_IPG     0x00001000 /* Inter-packet gap */
+#define SEEQ_HCTL_RFIX    0x00002000 /* At rxdc, clear end-of-packet */
+#define SEEQ_HCTL_EFIX    0x00004000 /* fixes intr status bit settings */
+#define SEEQ_HCTL_IFIX    0x00008000 /* enable startup timeouts */
+
+#endif /* !(_SGISEEQ_H) */
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
new file mode 100644 (file)
index 0000000..c42450a
--- /dev/null
@@ -0,0 +1,890 @@
+/*
+ * sonic.c
+ *
+ * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the onboard Sonic ethernet controller on Mips Jazz
+ * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
+ * perhaps others, too)
+ */
+
+static const char *version =
+       "sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n";
+
+/*
+ * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
+ * National Semiconductors data sheet for the DP83932B Sonic Ethernet
+ * controller, and the files "8390.c" and "skeleton.c" in this directory.
+ */
+
+#include <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:
+ */
diff --git a/drivers/net/sonic.h b/drivers/net/sonic.h
new file mode 100644 (file)
index 0000000..711c551
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Helpfile for sonic.c
+ *
+ * (C) Waldorf Electronics, Germany
+ * Written by Andreas Busse
+ *
+ * NOTE: most of the structure definitions here are endian dependent.
+ * If you want to use this driver on big endian machines, the data
+ * and pad structure members must be exchanged. Also, the structures
+ * need to be changed accordingly to the bus size. 
+ *
+ */
+
+#ifndef SONIC_H
+#define SONIC_H
+
+/*
+ * Macros to access SONIC registers
+ */
+#define SONIC_READ(reg) \
+       *((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+       *((volatile unsigned int *)base_addr+reg) = val
+
+
+/*
+ * SONIC register offsets
+ */
+#define SONIC_CMD              0x00
+#define SONIC_DCR              0x01
+#define SONIC_RCR              0x02
+#define SONIC_TCR              0x03
+#define SONIC_IMR              0x04
+#define SONIC_ISR              0x05
+
+#define SONIC_UTDA             0x06
+#define SONIC_CTDA             0x07
+
+#define SONIC_URDA             0x0d
+#define SONIC_CRDA             0x0e
+#define SONIC_EOBC             0x13
+#define SONIC_URRA             0x14
+#define SONIC_RSA              0x15
+#define SONIC_REA              0x16
+#define SONIC_RRP              0x17
+#define SONIC_RWP              0x18
+#define SONIC_RSC              0x2b
+
+#define SONIC_CEP              0x21
+#define SONIC_CAP2             0x22
+#define SONIC_CAP1             0x23
+#define SONIC_CAP0             0x24
+#define SONIC_CE               0x25
+#define SONIC_CDP              0x26
+#define SONIC_CDC              0x27
+
+#define SONIC_WT0              0x29
+#define SONIC_WT1              0x2a
+
+#define SONIC_SR               0x28
+
+
+/* test-only registers */
+
+#define SONIC_TPS              0x08
+#define SONIC_TFC              0x09
+#define SONIC_TSA0             0x0a
+#define SONIC_TSA1             0x0b
+#define SONIC_TFS              0x0c
+
+#define SONIC_CRBA0            0x0f
+#define SONIC_CRBA1            0x10
+#define SONIC_RBWC0            0x11
+#define SONIC_RBWC1            0x12
+#define SONIC_TTDA             0x20
+#define SONIC_MDT              0x2f
+
+#define SONIC_TRBA0            0x19
+#define SONIC_TRBA1            0x1a
+#define SONIC_TBWC0            0x1b
+#define SONIC_TBWC1            0x1c
+#define SONIC_LLFA             0x1f
+
+#define SONIC_ADDR0            0x1d
+#define SONIC_ADDR1            0x1e
+
+/*
+ * Error counters
+ */
+#define SONIC_CRCT              0x2c
+#define SONIC_FAET              0x2d
+#define SONIC_MPT               0x2e
+
+
+/*
+ * SONIC command bits
+ */
+
+#define SONIC_CR_LCAM           0x0200
+#define SONIC_CR_RRRA           0x0100
+#define SONIC_CR_RST            0x0080
+#define SONIC_CR_ST             0x0020
+#define SONIC_CR_STP            0x0010
+#define SONIC_CR_RXEN           0x0008
+#define SONIC_CR_RXDIS          0x0004
+#define SONIC_CR_TXP            0x0002
+#define SONIC_CR_HTX            0x0001
+
+/*
+ * SONIC data configuration bits
+ */
+
+#define SONIC_DCR_EXBUS         0x8000
+#define SONIC_DCR_LBR           0x2000
+#define SONIC_DCR_PO1           0x1000
+#define SONIC_DCR_PO0           0x0800
+#define SONIC_DCR_SBUS          0x0400
+#define SONIC_DCR_USR1          0x0200
+#define SONIC_DCR_USR0          0x0100
+#define SONIC_DCR_WC1           0x0080
+#define SONIC_DCR_WC0           0x0040
+#define SONIC_DCR_DW            0x0020
+#define SONIC_DCR_BMS           0x0010
+#define SONIC_DCR_RFT1          0x0008
+#define SONIC_DCR_RFT0          0x0004
+#define SONIC_DCR_TFT1          0x0002
+#define SONIC_DCR_TFT0          0x0001
+
+/*
+ * Constants for the SONIC receive control register.
+ */
+
+#define SONIC_RCR_ERR           0x8000
+#define SONIC_RCR_RNT           0x4000
+#define SONIC_RCR_BRD           0x2000
+#define SONIC_RCR_PRO           0x1000
+#define SONIC_RCR_AMC           0x0800
+#define SONIC_RCR_LB1           0x0400
+#define SONIC_RCR_LB0           0x0200
+
+#define SONIC_RCR_MC            0x0100
+#define SONIC_RCR_BC            0x0080
+#define SONIC_RCR_LPKT          0x0040
+#define SONIC_RCR_CRS           0x0020
+#define SONIC_RCR_COL           0x0010
+#define SONIC_RCR_CRCR          0x0008
+#define SONIC_RCR_FAER          0x0004
+#define SONIC_RCR_LBK           0x0002
+#define SONIC_RCR_PRX           0x0001
+
+#define SONIC_RCR_LB_OFF        0
+#define SONIC_RCR_LB_MAC        SONIC_RCR_LB0
+#define SONIC_RCR_LB_ENDEC      SONIC_RCR_LB1
+#define SONIC_RCR_LB_TRANS      (SONIC_RCR_LB0 | SONIC_RCR_LB1)
+
+/* default RCR setup */
+
+#define SONIC_RCR_DEFAULT       (SONIC_RCR_BRD)
+
+
+/*
+ * SONIC Transmit Control register bits
+ */
+
+#define SONIC_TCR_PINTR         0x8000
+#define SONIC_TCR_POWC          0x4000
+#define SONIC_TCR_CRCI          0x2000
+#define SONIC_TCR_EXDIS         0x1000
+#define SONIC_TCR_EXD           0x0400
+#define SONIC_TCR_DEF           0x0200
+#define SONIC_TCR_NCRS          0x0100
+#define SONIC_TCR_CRLS          0x0080
+#define SONIC_TCR_EXC           0x0040
+#define SONIC_TCR_PMB           0x0008
+#define SONIC_TCR_FU            0x0004
+#define SONIC_TCR_BCM           0x0002
+#define SONIC_TCR_PTX           0x0001
+
+#define SONIC_TCR_DEFAULT       0x0000
+
+/* 
+ * Constants for the SONIC_INTERRUPT_MASK and
+ * SONIC_INTERRUPT_STATUS registers.
+ */
+
+#define SONIC_INT_BR           0x4000
+#define SONIC_INT_HBL          0x2000
+#define SONIC_INT_LCD           0x1000
+#define SONIC_INT_PINT          0x0800
+#define SONIC_INT_PKTRX         0x0400
+#define SONIC_INT_TXDN          0x0200
+#define SONIC_INT_TXER          0x0100
+#define SONIC_INT_TC            0x0080
+#define SONIC_INT_RDE           0x0040
+#define SONIC_INT_RBE           0x0020
+#define SONIC_INT_RBAE         0x0010
+#define SONIC_INT_CRC          0x0008
+#define SONIC_INT_FAE          0x0004
+#define SONIC_INT_MP           0x0002
+#define SONIC_INT_RFO          0x0001
+
+
+/*
+ * The interrupts we allow.
+ */
+
+#define SONIC_IMR_DEFAULT      (SONIC_INT_BR | \
+                               SONIC_INT_LCD | \
+                                SONIC_INT_PINT | \
+                                SONIC_INT_PKTRX | \
+                                SONIC_INT_TXDN | \
+                                SONIC_INT_TXER | \
+                                SONIC_INT_RDE | \
+                                SONIC_INT_RBE | \
+                                SONIC_INT_RBAE | \
+                                SONIC_INT_CRC | \
+                                SONIC_INT_FAE | \
+                                SONIC_INT_MP)
+
+
+#define        SONIC_END_OF_LINKS      0x0001
+
+
+/*
+ * structure definitions
+ */
+
+typedef struct {
+  u32 rx_bufadr_l;     /* receive buffer ptr */
+  u32 rx_bufadr_h;
+
+  u32 rx_bufsize_l;    /* no. of words in the receive buffer */
+  u32 rx_bufsize_h;
+} sonic_rr_t;
+
+/*
+ * Sonic receive descriptor. Receive descriptors are
+ * kept in a linked list of these structures.
+ */
+
+typedef struct {
+  u16 rx_status;       /* status after reception of a packet */
+  u16 pad0;
+  u16 rx_pktlen;       /* length of the packet incl. CRC */
+  u16 pad1;
+  
+  /*
+   * Pointers to the location in the receive buffer area (RBA)
+   * where the packet resides. A packet is always received into
+   * a contiguous piece of memory.
+   */
+  u16 rx_pktptr_l;
+  u16 pad2;
+  u16 rx_pktptr_h;
+  u16 pad3;
+
+  u16 rx_seqno;        /* sequence no. */
+  u16 pad4;
+
+  u16 link;            /* link to next RDD (end if EOL bit set) */
+  u16 pad5;
+
+  /*
+   * Owner of this descriptor, 0= driver, 1=sonic
+   */
+  
+  u16 in_use;  
+  u16 pad6;
+
+  caddr_t rda_next;            /* pointer to next RD */
+} sonic_rd_t;
+
+
+/*
+ * Describes a Transmit Descriptor
+ */
+typedef struct {
+  u16 tx_status;       /* status after transmission of a packet */
+  u16 pad0;            
+  u16 tx_config;       /* transmit configuration for this packet */
+  u16 pad1;            
+  u16 tx_pktsize;      /* size of the packet to be transmitted */
+  u16 pad2;            
+  u16 tx_frag_count;   /* no. of fragments */
+  u16 pad3;            
+
+  u16 tx_frag_ptr_l;
+  u16 pad4;            
+  u16 tx_frag_ptr_h;
+  u16 pad5;            
+  u16 tx_frag_size;
+  u16 pad6;            
+  
+  u16 link;            /* ptr to next descriptor */
+  u16 pad7;            
+} sonic_td_t;
+
+
+/*
+ * Describes an entry in the CAM Descriptor Area.
+ */
+
+typedef struct {
+  u16 cam_entry_pointer;
+  u16 pad;
+  u16 cam_frag2;
+  u16 pad2;
+  u16 cam_frag1;
+  u16 pad1;
+  u16 cam_frag0;
+  u16 pad0;
+} sonic_cd_t;
+
+#define CAM_DESCRIPTORS 16
+
+
+typedef struct {
+  sonic_cd_t cam_desc[CAM_DESCRIPTORS];
+  u16 cam_enable;
+  u16 pad;
+} sonic_cda_t;
+
+
+#endif /* SONIC_H */
index ae81e12604bf4a89d4e54cb424bc724e99a1a74e..8ca6b0b6c814dcbce811e36fb6431eb207debb41 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bwtwo.c,v 1.16 1997/06/04 08:27:26 davem Exp $
+/* $Id: bwtwo.c,v 1.17 1997/06/06 10:56:28 jj Exp $
  * bwtwo.c: bwtwo console driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -74,7 +74,8 @@ static int
 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;
index 2cb4c21c96696f45c5e26b1306ccc3e6e8f9dae6..a69c6f12c1219d881d7369acb91d9958a945bb8e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cgfourteen.c,v 1.22 1997/06/04 08:27:27 davem Exp $
+/* $Id: cgfourteen.c,v 1.23 1997/06/06 10:56:29 jj Exp $
  * cgfourteen.c: Sun SparcStation console support.
  *
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -166,7 +166,7 @@ cg14_mmap (struct inode *inode, struct file *file,
           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);
index e53fcf09e80e5d3dd255498dbc4da9a4b62202c7..8c0764acb2390d68f5dbf20880902073f7b1d794 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cgsix.c,v 1.30 1997/06/04 08:27:28 davem Exp $
+/* $Id: cgsix.c,v 1.32 1997/06/14 15:26:08 davem Exp $
  * cgsix.c: cgsix frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -233,7 +233,7 @@ cg6_mmap (struct inode *inode, struct file *file, 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;
        
        size = vma->vm_end - vma->vm_start;
         if (vma->vm_offset & ~PAGE_MASK)
@@ -247,7 +247,7 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
                switch (vma->vm_offset+page){
                case CG6_TEC:
                        map_size = PAGE_SIZE;
-                       map_offset = get_phys ((unsigned long)fb->info.cg6.tec);
+                       map_offset = get_phys ((unsigned long)fb->info.cg6.tec) & PAGE_MASK;
                        break;
                case CG6_FBC:
                        map_size = PAGE_SIZE;
@@ -259,18 +259,25 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
                        break;
                case CG6_THC:
                        map_size = PAGE_SIZE;
-                       map_offset = get_phys ((unsigned long)fb->info.cg6.thc);
+                       map_offset = get_phys ((unsigned long)fb->info.cg6.thc) & PAGE_MASK;
                        break;
                case CG6_BTREGS:
                        map_size = PAGE_SIZE;
                        map_offset = get_phys ((unsigned long)fb->info.cg6.bt);
                        break;
+
+               /* For Ultra, make sure the following two are right.
+                * The above two happen to work out (for example FBC and
+                * TEC will get mapped by one I/O page mapping because
+                * of the 8192 byte page size, same for FHC/THC.  -DaveM
+                */
+
                case CG6_DHC:
-                       map_size = PAGE_SIZE * 40;
+                       map_size = /* PAGE_SIZE * 40 */ (4096 * 40);
                        map_offset = get_phys ((unsigned long)fb->info.cg6.dhc);
                        break;
                case CG6_ROM:
-                       map_size = PAGE_SIZE * 16;
+                       map_size = /* PAGE_SIZE * 16 */ (4096 * 16);
                        map_offset = get_phys ((unsigned long)fb->info.cg6.rom);
                        break;
                case CG6_RAM:
@@ -449,14 +456,22 @@ __initfunc(void cg6_setup (fbinfo_t *fb, int slot, u32 cg6, int cg6_io))
                 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) {
index 0e1446c0e5ce32e505621463506035c619f8564c..b87a82e00437e84b35d5a15ce0a391e49de65661 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cgthree.c,v 1.21 1997/06/04 08:27:29 davem Exp $
+/* $Id: cgthree.c,v 1.22 1997/06/06 10:56:30 jj Exp $
  * cgtree.c: cg3 frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -96,7 +96,7 @@ cg3_mmap (struct inode *inode, struct file *file, 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;
        
        size = vma->vm_end - vma->vm_start;
         if (vma->vm_offset & ~PAGE_MASK)
index 029eac81bbb10d47e603a0c93dd8d6fbe4003bd7..52fded0c2ff635518d919c842bbd1bdd6e6f464f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fb.h,v 1.26 1997/04/17 02:29:33 miguel Exp $
+/* $Id: fb.h,v 1.27 1997/06/06 10:56:28 jj Exp $
  * fb.h: contains the definitions of the structures that various sun
  *       frame buffer can use to do console driver stuff.
  *
@@ -183,7 +183,7 @@ extern int con_height, con_linebytes;
 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);
 
index 61e646e9fd17682c5d684e31151db9db65cc8bbc..6b0bcbb121d81bb9508bcf905dd5865401f4ed27 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: leo.c,v 1.18 1997/06/04 08:27:30 davem Exp $
+/* $Id: leo.c,v 1.19 1997/06/06 10:56:30 jj Exp $
  * leo.c: SUNW,leo 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -143,7 +143,7 @@ leo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
          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)
index 1d3815dd33d15628062b6791b5856501418d010b..944b4c1cbc564ebc66b9fec3063411bf71dec0ae 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: suncons.c,v 1.63 1997/05/31 18:33:25 mj Exp $
+/* $Id: suncons.c,v 1.64 1997/06/06 10:56:25 jj Exp $
  *
  * suncons.c: Sun SparcStation console support.
  *
@@ -759,7 +759,7 @@ console_restore_palette (void)
                (*fb_restore_palette) (&fbinfo[0]);
 }
 
-unsigned int
+unsigned long
 get_phys (unsigned long addr)
 {
        return __get_phys(addr);
@@ -1641,51 +1641,55 @@ void memcpyw(unsigned short *to, unsigned short *from, unsigned int count)
 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];
index 68856c9eee7c738835936935c7e0dd33d4ca5cd6..d0a5db4e5763f1a8d157201c40a23b0f75927196 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sunfb.c,v 1.23 1997/05/31 18:33:26 mj Exp $
+/* $Id: sunfb.c,v 1.24 1997/06/06 10:56:24 jj Exp $
  * sunfb.c: Sun generic frame buffer support.
  *
  * Copyright (C) 1995, 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -132,7 +132,7 @@ fb_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
                if ((index < 0) || (index > 255))
                        return -EINVAL;
                if (index + count > 256)
-                       count = 256 - cmap->index;
+                       count = 256 - index;
                __get_user_ret(rp, &cmap->red, -EFAULT);
                __get_user_ret(gp, &cmap->green, -EFAULT);
                __get_user_ret(bp, &cmap->blue, -EFAULT);
@@ -146,7 +146,7 @@ fb_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
                        __put_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
                        rp++; gp++; bp++;
                }
-               (*fb->loadcmap)(fb, cmap->index, count);
+               (*fb->loadcmap)(fb, index, count);
                 break;                 
 
        }
@@ -164,13 +164,13 @@ fb_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
                if ((index < 0) || (index > 255))
                        return -EINVAL;
                if (index + count > 256)
-                       count = 256 - cmap->index;
+                       count = 256 - index;
                __get_user_ret(rp, &cmap->red, -EFAULT);
                __get_user_ret(gp, &cmap->green, -EFAULT);
                __get_user_ret(bp, &cmap->blue, -EFAULT);
-               if(verify_area (VERIFY_READ, rp, cmap->count)) return -EFAULT;
-               if(verify_area (VERIFY_READ, gp, cmap->count)) return -EFAULT;
-               if(verify_area (VERIFY_READ, bp, cmap->count)) return -EFAULT;
+               if(verify_area (VERIFY_READ, rp, count)) return -EFAULT;
+               if(verify_area (VERIFY_READ, gp, count)) return -EFAULT;
+               if(verify_area (VERIFY_READ, bp, count)) return -EFAULT;
 
                end = index + count;
                for (i = index; i < end; i++){
@@ -179,7 +179,7 @@ fb_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
                        __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;                 
        }
 
index db66383ac40795ca583f36e5778f4f8cd0649ba6..e2fe18e6f80ebe7f72f7144e076180cf65eec2d3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: tcx.c,v 1.15 1997/06/04 08:27:32 davem Exp $
+/* $Id: tcx.c,v 1.16 1997/06/06 10:56:31 jj Exp $
  * tcx.c: SUNW,tcx 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -110,7 +110,8 @@ tcx_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
          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 };
index d2ac4d1353463a9c3959fc300c63cd8105e25bab..bb8d20fe68e642ce8a90975e6946b737e3d3c95d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: weitek.c,v 1.12 1997/06/04 08:27:34 davem Exp $
+/* $Id: weitek.c,v 1.13 1997/06/06 10:56:31 jj Exp $
  * weitek.c: Tadpole P9100/P9000 console driver
  *
  * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
@@ -41,7 +41,7 @@ weitek_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma,
            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)
index 4dbb76c85f47bf7b42443ecb7fe06b5f055277ef..ed4401ce5f824c46a212b1f5fe48ce1cbea2bee2 100644 (file)
@@ -21,7 +21,7 @@
 
 static struct file_system_type autofs_fs_type = {
        "autofs",
-       FS_NO_DCACHE,
+       0 /* FS_NO_DCACHE doesn't work correctly */,
        autofs_read_super,
        NULL
 };
index bd06972f3ac4ff6978aa54ebf88cc4ff4dc36296..87b6470273d9dd86401b6ca8d2f8b5eff2706354 100644 (file)
@@ -495,17 +495,18 @@ static inline void insert_into_queues(struct buffer_head * bh)
 
 static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
 {              
-       struct buffer_head * tmp;
-
-       for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
-               if (tmp->b_blocknr == block && tmp->b_dev == dev) {
-                       if (tmp->b_size == size)
-                               return tmp;
+       struct buffer_head * next;
 
-                       printk("VFS: Wrong blocksize on device %s\n",
-                              kdevname(dev));
-                       return NULL;
-               }
+       next = hash(dev,block);
+       for (;;) {
+               struct buffer_head *tmp = next;
+               if (!next)
+                       break;
+               next = tmp->b_next;
+               if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)
+                       continue;
+               return tmp;
+       }
        return NULL;
 }
 
@@ -518,10 +519,11 @@ static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
  */
 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);
index d1e9bc6caaf8bf11edbd3e059a98385d2ef6561e..3fdc0be0aef8d3153ef15d2b834b670de67c28e6 100644 (file)
 
 /* Well-known binary file extensions - of course there are many more */
 
-static char bin_extensions[] =
-  "EXE" "COM" "BIN" "APP" "SYS" "DRV" "OVL" "OVR" "OBJ" "LIB" "DLL" "PIF" /* program code */
-  "ARC" "ZIP" "LHA" "LZH" "ZOO" "TAR" "Z  " "ARJ"      /* common archivers */
-  "TZ " "TAZ" "TZP" "TPZ"              /* abbreviations of tar.Z and tar.zip */
-  "GZ " "TGZ" "DEB"                    /* .gz, .tar.gz and Debian packages   */
-  "GIF" "BMP" "TIF" "GL " "JPG" "PCX"  /* graphics */
-  "TFM" "VF " "GF " "PK " "PXL" "DVI"; /* TeX */
+static char ascii_extensions[] =
+  "TXT" "ME " "HTM" "1ST" "LOG" "   "  /* text files */
+  "C  " "H  " "CPP" "LIS" "PAS" "FOR"  /* programming languages */
+  "F  " "MAK" "INC" "BAS"              /* programming languages */
+  "BAT" "SH"                           /* program code :) */
+  "INI "                               /* config files */
+  "PBM" "PGM" "DXF"                    /* graphics */
+  "TEX";                               /* TeX */
 
 
 /*
@@ -62,9 +63,9 @@ int is_binary(char conversion,char *extension)
                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");
index 72ca3e6dd27038d98efb769e27348c40522dab14..83309f3a6c7e77e4adf15a02f03040ed197d3818 100644 (file)
@@ -408,7 +408,7 @@ int ncp_current_malloced;
 
 static struct file_system_type ncp_fs_type = {
        "ncpfs",
-       FS_NO_DCACHE,
+       0 /* FS_NO_DCACHE doesn't work correctly */,
         ncp_read_super,
        NULL
 };
index 5ab9600e93a80f0419ca404cf1cbd03ed6aea8e6..b9156417836bb182b36550eb391700e01333c80d 100644 (file)
@@ -435,7 +435,7 @@ done:
  */
 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
 };
index 71c29dd759c80ef3af1491c14693e3ec8fd63ec0..d3077ea79bebeb77f572ee5505482c282a5e2d9c 100644 (file)
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(proc_openprom_deregister);
 
 static struct file_system_type proc_fs_type = {
        "proc", 
-       FS_NO_DCACHE,
+       0 /* FS_NO_DCACHE doesn't work correctly */,
        proc_read_super, 
        NULL
 };
index 0ddda855d4fe15790e512dfec1c2ccd414933f1e..5d936ee59ba39e97d474290f2db61176e80e3c42 100644 (file)
@@ -584,7 +584,7 @@ static struct super_operations romfs_ops = {
 
 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
 };
index 20738b0d2f3b1677696caf96c8e8e56df52a1610..75d3dbff711d3c5a06ea457bad745b7c2b34ca00 100644 (file)
@@ -431,7 +431,7 @@ int smb_current_vmalloced;
 
 static struct file_system_type smb_fs_type = {
        "smbfs",
-       FS_NO_DCACHE,
+       0 /* FS_NO_DCACHE doesn't work correctly */,
        smb_read_super,
        NULL
 };
index 8a5efcd2b5524f150f097ca3c202a5d351b502c1..94fc31fc05b1aef2a1e85d1583194b13d0b2f286 100644 (file)
@@ -602,10 +602,7 @@ static int do_umount(kdev_t dev,int unmount_root)
        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
@@ -614,6 +611,13 @@ static int do_umount(kdev_t dev,int unmount_root)
        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;
index bb4f71de877ef39f4fc2a6b7fd362b2283e9a168..0337b92b3db7e91bc6ba9486fa101e9f83887b07 100644 (file)
@@ -83,6 +83,8 @@
 #define TIOCGETD       0x5424
 #define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
 
 #define TIOCSERCONFIG  0x5453
 #define TIOCSERGWILD   0x5454
index 60e0806e54e59bb1f701bb12a6c0de63410ad0b2..ae04e1a55fd19f4719e59bf4f5eafb8523191766 100644 (file)
@@ -44,6 +44,9 @@
 #define TIOCGETD       0x5424
 #define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
+
 #define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX                0x5451
 #define FIOASYNC       0x5452
index 069c7a1a8d9ca58e8b970385098aaa53a41d7962..66efafee95b61ca67453c9579ac083e8b5eeb98c 100644 (file)
 #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> */
 
index 77ad866b8b4213b0c5a57e5029f132c713b6cbcf..b4a95af6192e5f4340273c2c00a3d2cb0a15773e 100644 (file)
@@ -44,6 +44,9 @@
 #define TIOCGETD       0x5424
 #define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
+
 #define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX                0x5451
 #define FIOASYNC       0x5452
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
new file mode 100644 (file)
index 0000000..3925948
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * Defitions for the address spaces of the MIPS CPUs.
+ */
+#ifndef __ASM_MIPS_ADDRSPACE_H
+#define __ASM_MIPS_ADDRSPACE_H
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#define PHYSADDR(a)            (((unsigned long)(a)) & 0x1fffffff)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KSEG0ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
+#define KSEG1ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
+#define KSEG2ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
+#define KSEG3ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+
+/*
+ * Memory segments (64bit kernel mode addresses)
+ */
+#define XKUSEG                  0x0000000000000000
+#define XKSSEG                  0x4000000000000000
+#define XKPHYS                  0x8000000000000000
+#define XKSEG                   0xc000000000000000
+#define CKSEG0                  0xffffffff80000000
+#define CKSEG1                  0xffffffffa0000000
+#define CKSSEG                  0xffffffffc0000000
+#define CKSEG3                  0xffffffffe0000000
+
+#endif /* __ASM_MIPS_ADDRSPACE_H */
index 6d923f15b426e28a9bb3c507b9ad858a201d07b2..cd4dcf2845f1cb5b2cb4741c0911a12903cd8896 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
  * Some useful macros for MIPS assembler code
  *
@@ -16,9 +16,7 @@
 #ifndef        __ASM_ASM_H
 #define        __ASM_ASM_H
 
-#include <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
@@ -143,68 +126,19 @@ symbol                    =       value
 #define TTABLE(string)                                  \
                .text;                                  \
                .word   1f;                             \
+               .previous;                              \
                .data;                                  \
 1:             .asciz  string;                         \
-               .text;
+               .previous
 
 /*
- * Move to kernel mode and disable interrupts
- * Set cp0 enable bit as sign that we're running on the kernel stack
- * Use with .set noat!
- * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
- * means that another three instructions will be executed with interrupts
- * disabled.
- */
-#define CLI                                             \
-               mfc0    AT,CP0_STATUS;                  \
-               li      t0,ST0_CU0|0x1f;                \
-               or      AT,t0;                          \
-               xori    AT,0x1f;                        \
-               mtc0    AT,CP0_STATUS;                  \
-
-/*
- * Move to kernel mode and enable interrupts
- * Set cp0 enable bit as sign that we're running on the kernel stack
- * Use with .set noat!
- * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
- * means that another three instructions will be executed with interrupts
- * disabled.  Arch/mips/kernel/r4xx0.S makes use of this fact.
- */
-#define STI                                             \
-               mfc0    AT,CP0_STATUS;                  \
-               li      t0,ST0_CU0|0x1f;                \
-               or      AT,t0;                          \
-               xori    AT,0x1e;                        \
-               mtc0    AT,CP0_STATUS;                  \
-
-/*
- * Special nop to fill load delay slots
- */
-#ifndef __R4000__
-#define NOP     nop
-#else
-#define NOP
-#endif
-
-/*
- * Return from exception
- */
-#if defined (CONFIG_CPU_R3000)
-#define ERET rfe
-#elif defined (CONFIG_CPU_R4X00) || defined (CONFIG_CPU_R4600)
-#define ERET                                            \
-               .set    mips3;                          \
-               eret;                                   \
-               .set    mips0
-#else
-#error "Implement ERET macro!"
-#endif
-
-/*
- * R8000/R10000 (MIPS ISA IV) pref instruction.
+ * MIPS IV pref instruction.
  * Use with .set noreorder only!
+ *
+ * MIPS IV implementations are free to treat this as a nop.  The R5000
+ * is one of them.  So we should have an option not to use this instruction.
  */
-#if defined (CONFIG_CPU_R8000) || defined(CONFIG_CPU_R10000)
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
 #define PREF(hint,addr)                                 \
                pref    hint,addr
 #define PREFX(hint,addr)                                \
@@ -215,34 +149,226 @@ symbol                   =       value
 #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 */
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
new file mode 100644 (file)
index 0000000..e99b6f6
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: asmmacro.h,v 1.1 1997/06/06 09:38:18 ralf Exp $
+ * asmmacro.h: Assembler macros to make things easier to read.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef __MIPS_ASMMACRO_H
+#define __MIPS_ASMMACRO_H
+
+#include <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) */
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
new file mode 100644 (file)
index 0000000..7b11877
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ * But use these as seldom as possible since they are much more slower
+ * than regular operations.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_ATOMIC_H
+#define __ASM_MIPS_ATOMIC_H
+
+#include <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 */
index 2f204b54a5c2f67f08ea9e08e24311412aab0aaa..59a6ccbbad439a16e2c98d1a7568c504a1ded0fd 100644 (file)
@@ -5,15 +5,55 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994, 1995  Ralf Baechle
+ * Copyright (c) 1994, 1995, 1996  Ralf Baechle
  */
 #ifndef __ASM_MIPS_BITOPS_H
 #define __ASM_MIPS_BITOPS_H
 
-#if __mips > 1
+#ifdef __KERNEL__
+
+#include <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;
 
@@ -30,13 +105,12 @@ extern __inline__ int set_bit(int nr, void *addr)
        do {
                mw = load_linked(addr);
                retval = (mask & mw) != 0;
-               }
-       while (!store_conditional(addr, mw|mask));
+       } while (!store_conditional(addr, mw|mask));
 
        return retval;
 }
 
-extern __inline__ int clear_bit(int nr, void *addr)
+extern __inline__ int test_and_clear_bit(int nr, void *addr)
 {
        int     mask, retval, mw;
 
@@ -51,7 +125,7 @@ extern __inline__ int clear_bit(int nr, void *addr)
        return retval;
 }
 
-extern __inline__ int change_bit(int nr, void *addr)
+extern __inline__ int test_and_change_bit(int nr, void *addr)
 {
        int     mask, retval, mw;
 
@@ -60,124 +134,165 @@ extern __inline__ int change_bit(int nr, void *addr)
        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;
@@ -185,26 +300,32 @@ extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
 
 extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
 {
-       unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+       unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
        int set = 0, bit = offset & 31, res;
+       unsigned long dummy;
        
        if (bit) {
                /*
                 * Look for zero in first byte
                 */
+#ifdef __MIPSEB__
+#error "Fix this for big endian byte order"
+#endif
                __asm__(".set\tnoreorder\n\t"
                        ".set\tnoat\n"
-                       "1:\tand\t$1,%2,%1\n\t"
-                       "beq\t$0,$1,2f\n\t"
-                       "sll\t%2,%2,1\n\t"
-                       "bne\t$0,%2,1b\n\t"
-                       "addiu\t%0,%0,1\n\t"
+                       "1:\tand\t$1,%4,%1\n\t"
+                       "beqz\t$1,1f\n\t"
+                       "sll\t%1,%1,1\n\t"
+                       "bnez\t%1,1b\n\t"
+                       "addiu\t%0,1\n\t"
                        ".set\tat\n\t"
                        ".set\treorder\n"
-                       : "=r" (set)
-                       : "r" (*p >> bit),
-                         "r" (1),
-                         "0" (0)
+                       "1:"
+                       : "=r" (set),
+                         "=r" (dummy)
+                       : "0" (0),
+                         "1" (1 << bit),
+                         "r" (*p)
                        : "$1");
                if (set < (32 - bit))
                        return set + offset;
@@ -214,10 +335,12 @@ extern __inline__ int find_next_zero_bit (void * addr, int size, int 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..
@@ -227,7 +350,7 @@ extern __inline__ unsigned long ffz(unsigned long word)
        unsigned int    __res;
        unsigned int    mask = 1;
 
-       __asm__ __volatile__ (
+       __asm__ (
                ".set\tnoreorder\n\t"
                ".set\tnoat\n\t"
                "move\t%0,$0\n"
@@ -239,11 +362,183 @@ extern __inline__ unsigned long ffz(unsigned long word)
                ".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 */
index bd8fc4d7e9c3dfa3b73128ed8dd5b9b50da40102..e723cae219832a3468c4bd4760be33f773cd47d0 100644 (file)
@@ -1,11 +1,8 @@
 /*
  * bootinfo.h -- Definition of the Linux/MIPS boot information structure
  *
- * Copyright (C) 1994 by Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * Based on Linux/68k linux/include/linux/bootstrap.h
- * Copyright (C) 1992 by Greg Harp
+ * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
+ *                             Stoned Elipot and Paul M. Antoine.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
 #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__ */
 
diff --git a/include/asm-mips/branch.h b/include/asm-mips/branch.h
new file mode 100644 (file)
index 0000000..08dda21
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Branch and jump emulation.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <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;
+}
index 41ca733661c12d713fa5b7c420813056e6c39594..5f00d4508ffe71d00bcad6a89f57722a27b9140e 100644 (file)
  *     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;
index 3085c9c0c8ed9fd65a6f4d613f8f36631278f87e..92e3b8863f50a60631566d0b78eda5ac3f6a7dfa 100644 (file)
+/*
+ * 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 */
index 604834774e6165a3168be3a65858c116b791ec7b..83211ad986d3fc2642e40347e6754e46693866bc 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * include/asm-mips/cache.h
  */
-#ifndef __ARCH_MIPS_CACHE_H
-#define __ARCH_MIPS_CACHE_H
+#ifndef __ASM_MIPS_CACHE_H
+#define __ASM_MIPS_CACHE_H
 
 /* bytes per L1 cache line */
 #define        L1_CACHE_BYTES  32      /* a guess */
 
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
-#endif
+#endif /* __ASM_MIPS_CACHE_H */
index bd34ecec79ee06cabd2b807b9c03d788bce65c6e..214d289182dd5de64ecf6e78c903242b2b45e0fa 100644 (file)
@@ -1,16 +1,11 @@
 /*
- * 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 */
diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h
new file mode 100644 (file)
index 0000000..66b0b36
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Cache operations for the cache instruction.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * (C) Copyright 1996, 1997 by Ralf Baechle
+ */
+#ifndef        __ASM_MIPS_CACHEOPS_H
+#define        __ASM_MIPS_CACHEOPS_H
+
+/*
+ * Cache Operations
+ */
+#define Index_Invalidate_I      0x00
+#define Index_Writeback_Inv_D   0x01
+#define Index_Invalidate_SI     0x02
+#define Index_Writeback_Inv_SD  0x03
+#define Index_Load_Tag_I       0x04
+#define Index_Load_Tag_D       0x05
+#define Index_Load_Tag_SI      0x06
+#define Index_Load_Tag_SD      0x07
+#define Index_Store_Tag_I      0x08
+#define Index_Store_Tag_D      0x09
+#define Index_Store_Tag_SI     0x0A
+#define Index_Store_Tag_SD     0x0B
+#define Create_Dirty_Excl_D    0x0d
+#define Create_Dirty_Excl_SD   0x0f
+#define Hit_Invalidate_I       0x10
+#define Hit_Invalidate_D       0x11
+#define Hit_Invalidate_SI      0x12
+#define Hit_Invalidate_SD      0x13
+#define Fill                   0x14
+#define Hit_Writeback_Inv_D    0x15
+                                       /* 0x16 is unused */
+#define Hit_Writeback_Inv_SD   0x17
+#define Hit_Writeback_I                0x18
+#define Hit_Writeback_D                0x19
+                                       /* 0x1a is unused */
+#define Hit_Writeback_SD       0x1b
+                                       /* 0x1c is unused */
+                                       /* 0x1e is unused */
+#define Hit_Set_Virtual_SI     0x1e
+#define Hit_Set_Virtual_SD     0x1f
+
+#endif /* __ASM_MIPS_CACHEOPS_H */
index 034aa3d0bf6417f857a4b0faae37e0c2fa24a3f2..c5f9d20c7ee3c607bf71f013768dadd5acebd817 100644 (file)
@@ -31,14 +31,46 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
 
 /*
- * the same as csum_partial, but copies from user space (but on the alpha
+ * the same as csum_partial, but copies from user space (but on MIPS
  * we have just one address space, so this is identical to the above)
+ *
+ * this is obsolete and will go away.
  */
 #define csum_partial_copy_fromuser csum_partial_copy
   
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+/*
+ *     Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned short int csum_fold(unsigned int sum)
+{
+       unsigned int __res;
+
+    __asm__("
+       .set    noat
+       srl     $1,%0,16
+       andi    %0,0xffff
+       addu    $1,%0
+       srl     %0,$1,16                # addup halfword carry
+       andi    $1,0xffff
+       addu    $1,%0
+       nor     %0,$0,$1
+       .set    at"
+       : "=r"(__res)
+       : "0" (sum)
+       : "$1");
+
+       return __res;
+}
 /*
  *     This is a version of ip_compute_csum() optimized for IP headers,
  *     which always checksum on 4 octet boundaries.
@@ -49,54 +81,48 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
 static inline unsigned short ip_fast_csum(unsigned char * iph,
                                          unsigned int ihl)
 {
-       unsigned short int sum;
-       unsigned long   dummy1, dummy2;
+       unsigned int sum;
+       unsigned long dummy;
 
        /*
-        * This is optimized for 32-bit MIPS processors.
-        * I tried it in plain C but the generated code looks to bad to
-        * use with old first generation MIPS CPUs.
-        * Using 64-bit code could even further improve these routines.
+        * This is for 32-bit MIPS processors.
         */
-       __asm__("
+       __asm__ __volatile__("
        .set    noreorder
        .set    noat
-       lw      %0,(%3)
-       subu    %1,4
-       blez    %1,2f
-       sll     %1,%4,2                 # delay slot
-       lw      %2,4(%3)
-       addu    %1,%3                   # delay slot
-       addu    %0,%2
-       sltu    $1,%0,%2
-       lw      %2,8(%3)
+       lw      %0,(%1)
+       subu    %2,4
+       #blez   %2,2f
+       sll     %2,2                    # delay slot
+
+       lw      %3,4(%1)
+       addu    %2,%1                   # delay slot
+       addu    %0,%3
+       sltu    $1,%0,%3
+       lw      %3,8(%1)
        addu    %0,$1
-       addu    %0,%2
-       sltu    $1,%0,%2
-       lw      %2,12(%3)
+       addu    %0,%3
+       sltu    $1,%0,%3
+       lw      %3,12(%1)
        addu    %0,$1
-       addu    %0,%2
-       sltu    $1,%0,%2
+       addu    %0,%3
+       sltu    $1,%0,%3
        addu    %0,$1
-1:     lw      %2,16(%3)
-       addu    %1,4
-       addu    %0,%2
-       sltu    $1,%0,%2
-       bne     %1,%3,1b
+
+1:     lw      %3,16(%1)
+       addiu   %1,4
+       addu    %0,%3
+       sltu    $1,%0,%3
+       bne     %2,%1,1b
        addu    %0,$1                   # delay slot
-       srl     $1,%0,16
-       addu    %0,$1
-       sltu    $1,%0,$1
-       addu    %0,$1
-       nor     %0,$0,%0
-       andi    %0,0xffff
+
 2:     .set    at
        .set    reorder"
-       : "=r" (sum), "=r" (dummy1), "=r" (dummy2)
-       : "r" (iph), "r"(ihl)
+       : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
+       : "1" (iph), "2" (ihl)
        : "$1");
 
-       return sum;
+       return csum_fold(sum);
 }
 
 /*
@@ -120,57 +146,47 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
        addu    %0,%4
        sltu    $1,%0,%4
        addu    %0,$1
+
        srl     $1,%0,16
+       andi    %0,0xffff
        addu    %0,$1
-       sltu    $1,%0,$1
+       srl     $1,%0,16                # addup halfword carry
+       andi    %0,0xffff
        addu    %0,$1
        nor     %0,$0,%0
-       andi    %0,0xffff
        .set    at"
        : "=r" (sum)
-       : "0" (daddr), "r"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
+       : "0" (daddr), "r"(saddr),
+#ifdef __MIPSEL__
+           "r" ((ntohs(len)<<16)+proto*256),
+#else
+           "r" (((proto)<<16)+len),
+#endif
+           "r"(sum)
        : "$1");
 
        return (unsigned short)sum;
 }
 
-/*
- *     Fold a partial checksum without adding pseudo headers
- */
-static inline unsigned short int csum_fold(unsigned int sum)
-{
-    __asm__("
-       .set    noat
-       srl     $1,%0,16
-       addu    %0,$1
-       sltu    $1,%0,$1
-       nor     %0,$0,%0
-       andi    %0,0xffff
-       .set    at"
-       : "=r"(sum)
-       : "0" (sum)
-       : "$1");
-
-       return sum;
-}
 /*
  * this routine is used for miscellaneous IP-like checksums, mainly
  * in icmp.c
  */
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
     unsigned short int sum;
 
     __asm__("
        .set    noat
        srl     $1,%0,16
+       andi    %0,0xffff
        addu    %0,$1
        sltu    $1,%0,$1
+       addu    %0,$1
        nor     %0,$0,%0
-       andi    %0,0xffff
        .set    at"
        : "=r"(sum)
-       : "r" (csum_partial(buff, len, 0))
+       : "0" (csum_partial(buff, len, 0))
        : "$1");
 
        return sum;
@@ -183,9 +199,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
                                                     unsigned short proto,
                                                     unsigned int sum) 
 {
-       unsigned long scratch;
-
-        __asm__("
+       __asm__("
                .set    noreorder
                .set    noat
                addu    %0,%5           # proto (long in network byte order)
@@ -234,14 +248,13 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
                addu    %0,%1
                sltu    $1,%0,$1
                .set    noat
-               .set    noreorder
-                "
-                : "=r" (sum),
-                 "=r" (scratch)
-                : "r" (saddr),
+               .set    noreorder"
+               : "=r" (sum),
+                 "=r" (proto)
+               : "r" (saddr),
                  "r" (daddr),
-                  "0" (htonl((__u32) (len))),
-                 "r" (htonl(proto)),
+                 "0" (htonl((__u32) (len))),
+                 "1" (htonl(proto)),
                  "r"(sum)
                : "$1");
 
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
new file mode 100644 (file)
index 0000000..d0ac486
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: cpu.h,v 1.1 1997/06/06 09:38:41 ralf Exp $
+ * cpu.h: Values of the PRId register used to match up
+ *        various MIPS cpu types.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_CPU_H
+#define _MIPS_CPU_H
+
+/*
+ * Assigned values for the product ID register.  In order to detect a
+ * certain CPU type exactly eventually additional registers may need to
+ * be examined.
+ */
+#define PRID_IMP_R2000    0x0100
+#define PRID_IMP_R3000    0x0200
+#define PRID_IMP_R6000    0x0300
+#define PRID_IMP_R4000    0x0400
+#define PRID_IMP_R6000A   0x0600
+#define PRID_IMP_R10000   0x0900
+#define PRID_IMP_R4300    0x0b00
+#define PRID_IMP_R8000    0x1000
+#define PRID_IMP_R4600    0x2000
+#define PRID_IMP_R4700    0x2100
+#define PRID_IMP_R4640    0x2200
+#define PRID_IMP_R4650    0x2200               /* Same as R4640 */
+#define PRID_IMP_R5000    0x2300
+#define PRID_IMP_SONIC    0x2400
+#define PRID_IMP_MAGIC    0x2500
+#define PRID_IMP_RM7000   0x2700
+#define PRID_IMP_NEVADA   0x2800               /* RM5260 ??? */
+
+#define PRID_IMP_UNKNOWN  0xff00
+
+#define PRID_REV_R4400    0x0040
+#define PRID_REV_R3000A   0x0030
+#define PRID_REV_R3000    0x0020
+#define PRID_REV_R2000A   0x0010
+
+#endif /* !(_MIPS_CPU_H) */
index 80f435c564611182c1da071a88dcdd86e9a98df6..7d1547b3c21f306acbde5e2e1eac49d1ff0cbc58 100644 (file)
@@ -1,12 +1,48 @@
-#ifndef _MIPS_CURRENT_H
-#define _MIPS_CURRENT_H
+#ifndef __ASM_MIPS_CURRENT_H
+#define __ASM_MIPS_CURRENT_H
 
-/* Some architectures may want to do something "clever" here since
- * this is the most frequently accessed piece of data in the entire
- * kernel.  For an example, see the Sparc implementation where an
- * entire register is hard locked to contain the value of current.
+#ifdef __LANGUAGE_C__
+
+static inline struct task_struct *__get_current(void)
+{
+       struct task_struct *__current;
+
+       __asm__("ori\t%0,$29,%1\n\t"
+               "xori\t%0,%1"
+                :"=r" (__current)
+                :"ir" (8191UL));
+
+       return __current;
+}
+
+#define current __get_current()
+
+#endif /* __LANGUAGE_C__ */
+#ifdef __LANGUAGE_ASSEMBLY__
+
+/*
+ * Get current task pointer
+ */
+#define GET_CURRENT(reg)                       \
+       lui     reg, %hi(kernelsp);             \
+       lw      reg, %lo(kernelsp)(reg);        \
+       ori     reg, 8191;                      \
+       xori    reg, 8191
+
+/*
+ * Special variant for use by exception handlers when the stack pointer
+ * is not loaded.
  */
-extern struct task_struct *current_set[NR_CPUS];
-#define current (current_set[smp_processor_id()])      /* Current on this processor */
+#define _GET_CURRENT(reg)                      \
+       lui     reg, %hi(kernelsp);             \
+       .set    push;                           \
+       .set    noreorder;                      \
+       lw      reg, %lo(kernelsp)(reg);        \
+       .set    pop;                            \
+       ori     reg, 8191;                      \
+       xori    reg, 8191
+
+
+#endif
 
-#endif /* !(_MIPS_CURRENT_H) */
+#endif /* __ASM_MIPS_CURRENT_H */
diff --git a/include/asm-mips/decstation.h b/include/asm-mips/decstation.h
new file mode 100644 (file)
index 0000000..ac04ff0
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Hardware info about DEC Personal DECStation systems (otherwise known
+ * as maxine or pmax (internal DEC codenames).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Paul M. Antoine, some code and definitions are
+ * by curteousy of Chris Fraser.
+ *
+ * This file is under construction - you were warned!
+ */
+
+#ifndef __ASM_MIPS_PMAX_H 
+#define __ASM_MIPS_PMAX_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb.
+ */
+
+#define PMAX_LOCAL_IO_SPACE     0xe0000000
+
+/*
+ * Motherboard regs (kseg1 addresses)
+ */
+#define PMAX_SSR_ADDR          0xbc040100              /* system support reg */
+
+/*
+ * SSR defines
+ */
+#define PMAX_SSR_LEDMASK       0x00000001              /* power LED */
+
+/*
+ * REX functions -- these are for the new TURBOchannel style ROMs
+ */
+#define REX_PROM_MAGIC  0x30464354                     /* passed in a2 */
+
+#define REX_GETBITMAP          0x84                    /* get mem bitmap */
+#define REX_GETCHAR            0x24                    /* getch() */
+#define REX_PUTCHAR            0x13                    /* putch() */
+#define REX_HALT               0x9c                    /* halt the system */
+#define REX_PRINTF             0x30                    /* printf() */
+#define REX_PUTS               0x2c                    /* puts() */
+#define REX_SLOTADDR           0x6c                    /* slotaddr */
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pmax_set_led(unsigned int bits)
+{
+       volatile unsigned int *led_register = (unsigned int *) PMAX_SSR_ADDR;
+
+       *led_register = bits & PMAX_SSR_LEDMASK;
+}
+
+/*
+ * Glue code to call the PMAX boot proms.
+ */
+extern asmlinkage void pmax_printf(const char *);
+
+#endif
+
+/*
+ * These are just hacked out of the JAZZ ones, no ideas really.
+ */
+#define PMAX_KEYBOARD_ADDRESS   0xe0005000
+#define PMAX_KEYBOARD_DATA      0xe0005000
+#define PMAX_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+       unsigned char data;
+       unsigned char command;
+} pmax_keyboard_hardware;
+
+typedef struct {
+       unsigned char pad0[3];
+       unsigned char data;
+       unsigned char pad1[3];
+       unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now.
+ */
+#define keyboard_hardware       pmax_keyboard_hardware
+
+#endif
+
+/*
+ * Serial ports on DEC - maybe!
+ */
+
+#define PMAX_SERIAL1_BASE       (unsigned int)0xe0006000
+#define PMAX_SERIAL2_BASE       (unsigned int)0xe0007000
+
+/*
+ * Dummy Device Address. Used in pmaxdma.c
+ */
+
+#define PMAX_DUMMY_DEVICE       0xe000d000
+     
+/*
+ * PMAX timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define PMAX_TIMER_INTERVAL     0xe0000228
+#define PMAX_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+       unsigned int bank2 : 3;
+       unsigned int bank1 : 3;
+       unsigned int mem_bus_width : 1;
+       unsigned int reserved2 : 1;
+       unsigned int page_mode : 1;
+       unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+       unsigned int reserved1 : 23;
+       unsigned int page_mode : 1;
+       unsigned int reserved2 : 1;
+       unsigned int mem_bus_width : 1;
+       unsigned int bank1 : 3;
+       unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PMAX_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * PMAX interrupt control registers
+ */
+#define PMAX_IO_IRQ_SOURCE      0xe0100000
+#define PMAX_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * PMAX interrupt enable bits
+ */
+#define PMAX_IE_PARALLEL            (1 << 0)
+#define PMAX_IE_FLOPPY              (1 << 1)
+#define PMAX_IE_SOUND               (1 << 2)
+#define PMAX_IE_VIDEO               (1 << 3)
+#define PMAX_IE_ETHERNET            (1 << 4)
+#define PMAX_IE_SCSI                (1 << 5)
+#define PMAX_IE_KEYBOARD            (1 << 6)
+#define PMAX_IE_MOUSE               (1 << 7)
+#define PMAX_IE_SERIAL1             (1 << 8)
+#define PMAX_IE_SERIAL2             (1 << 9)
+
+/*
+ * PMAX Interrupt Level definitions
+ */
+
+#define PMAX_TIMER_IRQ          0
+#define PMAX_KEYBOARD_IRQ       1
+#define PMAX_ETHERNET_IRQ       2 /* 15 */
+#define PMAX_SERIAL1_IRQ        3
+#define PMAX_SERIAL2_IRQ        4
+#define PMAX_PARALLEL_IRQ       5
+#define PMAX_FLOPPY_IRQ         6 /* needs to be consistent with floppy driver! */
+
+/*
+ * PMAX DMA Channels
+ * Note: Channels 4...7 are not used with respect to the Acer PICA-61
+ * chipset which does not provide these DMA channels.
+ */
+
+#define PMAX_SCSI_DMA           0              /* SCSI */
+#define PMAX_FLOPPY_DMA         1              /* FLOPPY */
+#define PMAX_AUDIOL_DMA         2              /* AUDIO L */
+#define PMAX_AUDIOR_DMA         3              /* AUDIO R */
+
+/*
+ * PMAX R4030 MCT_ADR chip (DMA controller)
+ * Note: Virtual Addresses !
+ */
+
+#define PMAX_R4030_CONFIG      0xE0000000      /* R4030 config register */
+#define PMAX_R4030_REVISION     0xE0000008     /* same as PICA_ASIC_REVISION */
+#define PMAX_R4030_INV_ADDR    0xE0000010      /* Invalid Address register */
+
+#define PMAX_R4030_TRSTBL_BASE  0xE0000018     /* Translation Table Base */
+#define PMAX_R4030_TRSTBL_LIM   0xE0000020     /* Translation Table Limit */
+#define PMAX_R4030_TRSTBL_INV   0xE0000028     /* Translation Table Invalidate */
+
+#define PMAX_R4030_CACHE_MTNC   0xE0000030     /* Cache Maintenance */
+#define PMAX_R4030_R_FAIL_ADDR  0xE0000038     /* Remote Failed Address */
+#define PMAX_R4030_M_FAIL_ADDR  0xE0000040     /* Memory Failed Adresss */
+
+#define PMAX_R4030_CACHE_PTAG   0xE0000048     /* I/O Cache Physical Tag */
+#define PMAX_R4030_CACHE_LTAG   0xE0000050     /* I/O Cache Logical Tag */
+#define PMAX_R4030_CACHE_BMASK  0xE0000058     /* I/O Cache Byte Mask */
+#define PMAX_R4030_CACHE_BWIN   0xE0000060     /* I/O Cache Buffer Window */
+
+/*
+ * Remote Speed Registers. 
+ *
+ *  0: free,      1: Ethernet,  2: SCSI,      3: Floppy,
+ *  4: RTC,       5: Kb./Mouse  6: serial 1,  7: serial 2,
+ *  8: parallel,  9: NVRAM,    10: CPU,      11: PROM,
+ * 12: reserved, 13: free,     14: 7seg LED, 15: ???
+ */
+
+#define PMAX_R4030_REM_SPEED   0xE0000070      /* 16 Remote Speed Registers */
+                                               /* 0xE0000070,78,80... 0xE00000E8 */
+#define PMAX_R4030_IRQ_ENABLE   0xE00000E8     /* Internal Interrupt Enable */
+
+#define PMAX_R4030_IRQ_SOURCE   0xE0000200     /* Interrupt Source Reg */
+#define PMAX_R4030_I386_ERROR   0xE0000208     /* i386/EISA Bus Error */
+
+
+/*
+ * Access the R4030 DMA and I/O Controller
+ */
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern inline unsigned short r4030_read_reg16(unsigned addr) {
+       unsigned short ret = *((volatile unsigned short *)addr);
+       __asm__ __volatile__("nop; nop; nop; nop;");
+       return ret;
+}
+
+extern inline unsigned int r4030_read_reg32(unsigned addr) {
+       unsigned int ret = *((volatile unsigned int *)addr);
+       __asm__ __volatile__("nop; nop; nop; nop;");
+       return ret;
+}
+
+extern inline void r4030_write_reg16(unsigned addr, unsigned val) {
+       *((volatile unsigned short *)addr) = val;
+       __asm__ __volatile__("nop; nop; nop; nop;");
+}
+
+extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) {
+       *((volatile unsigned int *)addr) = val;
+       __asm__ __volatile__("nop; nop; nop; nop;");
+}
+
+#endif /* !LANGUAGE_ASSEMBLY__ */
+
+       
+#endif /* __ASM_MIPS_PMAX_H */
index 36e3b66c5b3ac6d4049c1ef827d4dc458b5f8eda..ec2ad70f3091260f8403f48dcc8f00b485fff5c4 100644 (file)
@@ -4,11 +4,9 @@
 extern __inline__ void __delay(int loops)
 {
        __asm__ __volatile__ (
-               ".set\tnoreorder\n\t"
-               ".set\tnoat\n\t"
-               "1:\tbne\t$0,%0,1b\n\t"
-               "subu\t%0,%0,1\n\t"
-               ".set\tat\n\t"
+               ".set\tnoreorder\n"
+               "1:\tbnez\t%0,1b\n\t"
+               "subu\t%0,1\n\t"
                ".set\treorder"
                :"=r" (loops)
                :"0" (loops));
@@ -24,16 +22,24 @@ extern __inline__ void __delay(int 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.
diff --git a/include/asm-mips/deskstation.h b/include/asm-mips/deskstation.h
new file mode 100644 (file)
index 0000000..52b8cdf
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * SNI specific definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_DESKSTATION_H 
+#define __ASM_MIPS_DESKSTATION_H 
+
+#define RPC44_PORT_BASE        0xe2000000
+
+#endif /* __ASM_MIPS_DESKSTATION_H */
index d3070c7321467031838322eb1d30e74b587aa83f..320022c765eba564565c93aa541bf0d42150d214 100644 (file)
@@ -5,14 +5,15 @@
  * and John Boyd, Nov. 1992.
  *
  * NOTE: all this is true *only* for ISA/EISA expansions on Mips boards
- * and can only be used for expansion cards. Onboard DMA controller, such
+ * and can only be used for expansion cards. Onboard DMA controllers, such
  * as the R4030 on Jazz boards behave totally different!
  */
 
 #ifndef __ASM_MIPS_DMA_H
 #define __ASM_MIPS_DMA_H
 
-#include <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 */
@@ -276,9 +281,4 @@ static __inline__ int get_dma_residue(unsigned int dmanr)
 extern int request_dma(unsigned int dmanr, const char * device_id);    /* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);      /* release it again */
 
-/*
- * DMA memory allocation - formerly in include/linux/mm.h
- */
-#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), 1)
-
 #endif /* __ASM_MIPS_DMA_H */
index 8520a784f4b0862a0ced67fefd8a1a9c4b8ab62b..97e670510e4a153de6a88d3d5b56826772f0783e 100644 (file)
@@ -1,12 +1,9 @@
 #ifndef __ASM_MIPS_ELF_H
 #define __ASM_MIPS_ELF_H
 
-/*
- * ELF register definitions
- * This is "make it compile" stuff!
- */
-#define ELF_NGREG      32
-#define ELF_NFPREG     32
+/* ELF register definitions */
+#define ELF_NGREG      45
+#define ELF_NFPREG     33
 
 typedef unsigned long elf_greg_t;
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
@@ -17,17 +14,30 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 /*
  * 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 */
index f31e2b19f342efb312441f82b2d948f07b3ae09b..38fd881be709bf8be7cddccda7f0c551175bfcf7 100644 (file)
 #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    /* ??? */
 
index 13fa713402548703c3eee6b16146d08a36ce92cb..3606b252adaeeffb96c12004200e7ce0b553b5d9 100644 (file)
 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;
 
index 48331ca9d006c90fafac3de14c1325ae729fec2a..f639f5aed5e0346bbdbbffdae328a42b902e8d96 100644 (file)
@@ -10,6 +10,7 @@
 #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>
@@ -30,7 +31,6 @@
 #define fd_get_dma_residue()           feature->fd_get_dma_residue()
 #define fd_enable_irq()                        feature->fd_enable_irq()
 #define fd_disable_irq()               feature->fd_disable_irq()
-#define fd_cacheflush(addr, size)      feature->fd_cacheflush((void *)addr, size)
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
                                            SA_INTERRUPT|SA_SAMPLE_RANDOM, \
                                            "floppy", NULL)
 
 #define MAX_BUFFER_SECTORS 24
 
-static unsigned long mips_dma_mem_alloc(unsigned long size)
+/* Pure 2^n version of get_order */
+extern __inline__ int __get_order(unsigned long size)
+{
+       int order;
+
+       size = (size-1) >> (PAGE_SHIFT-1);
+       order = -1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       return order;
+}
+
+extern __inline__ unsigned long mips_dma_mem_alloc(unsigned long size)
 {
        int order = __get_order(size);
        unsigned long mem;
@@ -46,38 +60,36 @@ static unsigned long mips_dma_mem_alloc(unsigned long size)
        mem = __get_dma_pages(GFP_KERNEL,order);
        if(!mem)
                return 0;
-        if (boot_info.machtype == MACH_ACER_PICA_61 ||
-            boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||
-            boot_info.machtype == MACH_OLIVETTI_M700)
+#ifdef CONFIG_MIPS_JAZZ
+        if (mips_machgroup == MACH_GROUP_JAZZ)
                vdma_alloc(PHYSADDR(mem), size);
+#endif
        return mem;
 }
 
-static void mips_dma_mem_free(unsigned long addr, unsigned long size)
+extern __inline__ void mips_dma_mem_free(unsigned long addr, unsigned long size)
 {       
-        if (boot_info.machtype == MACH_ACER_PICA_61 ||
-            boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||
-            boot_info.machtype == MACH_OLIVETTI_M700)
+#ifdef CONFIG_MIPS_JAZZ
+        if (mips_machgroup == MACH_GROUP_JAZZ)
                vdma_free(PHYSADDR(addr));
+#endif
        free_pages(addr, __get_order(size));    
 }
 
-#define fd_dma_mem_alloc(mem,size) mips_dma_mem_alloc(mem,size)
-#define fd_dma_mem_free(mem) mips_dma_mem_free(mem)
+#define fd_dma_mem_alloc(size) mips_dma_mem_alloc(size)
+#define fd_dma_mem_free(mem,size) mips_dma_mem_free(mem,size)
 
 /*
  * And on Mips's the CMOS info fails also ...
  *
  * FIXME: This information should come from the ARC configuration tree
- *        or wherever a particular machine has stored this ...
+ *        or whereever a particular machine has stored this ...
  */
 #define FLOPPY0_TYPE 4         /* this is wrong for the Olli M700, but who cares... */
 #define FLOPPY1_TYPE 0
 
-#define FDC1                   ((boot_info.machtype == MACH_ACER_PICA_61 || \
-                               boot_info.machtype == MACH_MIPS_MAGNUM_4000 || \
-                               boot_info.machtype == MACH_OLIVETTI_M700) ? \
-                               0xe0003000 : 0x3f0)
+#define FDC1                   ((mips_machgroup == MACH_GROUP_JAZZ) ? \
+                               JAZZ_FDC_BASE : 0x3f0)
 static int FDC2=-1;
 
 #define N_FDC 1                        /* do you *really* want a second controller? */
diff --git a/include/asm-mips/hardirq.h b/include/asm-mips/hardirq.h
new file mode 100644 (file)
index 0000000..f372b24
--- /dev/null
@@ -0,0 +1,24 @@
+#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 */
diff --git a/include/asm-mips/ide.h b/include/asm-mips/ide.h
new file mode 100644 (file)
index 0000000..bda2720
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  linux/include/asm-mips/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the MIPS architecture specific IDE code.
+ */
+
+#ifndef __ASM_MIPS_IDE_H
+#define __ASM_MIPS_IDE_H
+
+#ifdef __KERNEL__
+
+typedef unsigned short ide_ioreg_t;
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS      4
+#endif
+
+#define ide_sti()      sti()
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
+{
+       switch (base) {
+               case 0x1f0: return 14;
+               case 0x170: return 15;
+               case 0x1e8: return 11;
+               case 0x168: return 10;
+               default:
+                       return 0;
+       }
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+       switch (index) {
+               case 0: return 0x1f0;
+               case 1: return 0x170;
+               case 2: return 0x1e8;
+               case 3: return 0x168;
+               default:
+                       return 0;
+       }
+}
+
+static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+       ide_ioreg_t port = base;
+       int i = 8;
+
+       while (i--)
+               *p++ = port++;
+       *p++ = base + 0x206;
+       if (irq != NULL)
+               *irq = 0;
+}
+
+typedef union {
+       unsigned all                    : 8;    /* all of the bits together */
+       struct {
+               unsigned head           : 4;    /* always zeros here */
+               unsigned unit           : 1;    /* drive select number, 0 or 1 */
+               unsigned bit5           : 1;    /* always 1 */
+               unsigned lba            : 1;    /* using LBA instead of CHS */
+               unsigned bit7           : 1;    /* always 1 */
+       } b;
+       } select_t;
+
+static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+                       unsigned long flags, const char *device, void *dev_id)
+{
+       return request_irq(irq, handler, flags, device, dev_id);
+}                      
+
+static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
+{
+       free_irq(irq, dev_id);
+}
+
+static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
+{
+       return check_region(from, extent);
+}
+
+static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
+{
+       request_region(from, extent, name);
+}
+
+static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
+{
+       release_region(from, extent);
+}
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
+{
+       return(1);
+}
+
+static __inline__ void ide_fix_driveid(struct hd_driveid *id)
+{
+}
+
+static __inline__ void ide_release_lock (int *ide_lock)
+{
+}
+
+static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
+{
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_MIPS_IDE_H */
index e4cbd35e3ff92e7bf07b6bca23f675215adcd8a3..cd963cb986738e8fa966189bc8882fa4e5e4b451 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _MIPS_INIT_H
-#define _MIPS_INIT_H
+#ifndef __ASM_MIPS_INIT_H
+#define __ASM_MIPS_INIT_H
 
 /* Throwing the initialization code and data out is not supported yet... */
 
@@ -11,4 +11,4 @@
 #define __FINIT
 #define __INITDATA
 
-#endif
+#endif /* __ASM_MIPS_INIT_H */
diff --git a/include/asm-mips/inst.h b/include/asm-mips/inst.h
new file mode 100644 (file)
index 0000000..8d7328f
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Format of an instruction in memory.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_INST_H
+#define __ASM_MIPS_INST_H
+
+/*
+ * Major opcodes; before MIPS IV cop1x was called cop3.
+ */
+enum major_op {
+       spec_op, bcond_op, j_op, jal_op,
+       beq_op, bne_op, blez_op, bgtz_op,
+       addi_op, addiu_op, slti_op, sltiu_op,
+       andi_op, ori_op, xori_op, lui_op,
+       cop0_op, cop1_op, cop2_op, cop1x_op,
+       beql_op, bnel_op, blezl_op, bgtzl_op,
+       daddi_op, daddiu_op, ldl_op, ldr_op,
+       major_1c_op, major_1d_op, major_1e_op, major_1f_op,
+       lb_op, lh_op, lwl_op, lw_op,
+       lbu_op, lhu_op, lwr_op, lwu_op,
+       sb_op, sh_op, swl_op, sw_op,
+       sdl_op, sdr_op, swr_op, cache_op,
+       ll_op, lwc1_op, lwc2_op, pref_op,
+       lld_op, ldc1_op, ldc2_op, ld_op,
+       sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
+       scd_op, sdc1_op, sdc2_op, sd_op
+};
+
+/*
+ * func field of spec opcode.
+ */
+enum spec_op {
+       sll_op, movc_op, srl_op, sra_op,
+       sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */
+       jr_op, jalr_op, movz_op, movn_op,
+       syscall_op, break_op, spim_op, sync_op,
+       mfhi_op, mthi_op, mflo_op, mtlo_op,
+       dsllv_op, spec2_unused_op, dsrlv_op, dsrav_op,
+       mult_op, multu_op, div_op, divu_op,
+       dmult_op, dmultu_op, ddiv_op, ddivu_op,
+       add_op, addu_op, sub_op, subu_op,
+       and_op, or_op, xor_op, nor_op,
+       spec3_unused_op, spec4_unused_op, slt_op, sltu_op,
+       dadd_op, daddu_op, dsub_op, dsubu_op,
+       tge_op, tgeu_op, tlt_op, tltu_op,
+       teq_op, spec5_unused_op, tne_op, spec6_unused_op,
+       dsll_op, spec7_unused_op, dsrl_op, dsra_op,
+       dsll32_op, spec8_unused_op, dsrl32_op, dsra32_op
+};
+
+/*
+ * rt field of bcond opcodes.
+ */
+enum rt_op {
+       bltz_op, bgez_op, bltzl_op, bgezl_op,
+       spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
+       tgei_op, tgeiu_op, tlti_op, tltiu_op,
+       teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
+       bltzal_op, bgezal_op, bltzall_op, bgezall_op
+       /*
+        * The others (0x14 - 0x1f) are unused.
+        */
+};
+
+/*
+ * rs field of cop opcodes.
+ */
+enum cop_op {
+       mfc_op        = 0x00, dmfc_op       = 0x01,
+       cfc_op        = 0x02, mtc_op        = 0x04,
+       dmtc_op       = 0x05, ctc_op        = 0x06,
+       bc_op         = 0x08, cop_op        = 0x10,
+       copm_op       = 0x18
+};
+
+/*
+ * func field of cop0 coi opcodes.
+ */
+enum cop0_coi_func {
+       tlbr_op       = 0x01, tlbwi_op      = 0x02,
+       tlbwr_op      = 0x06, tlbp_op       = 0x08,
+       rfe_op        = 0x10, eret_op       = 0x18
+};
+
+/*
+ * func field of cop0 com opcodes.
+ */
+enum cop0_com_func {
+       tlbr1_op      = 0x01, tlbw_op       = 0x02,
+       tlbp1_op      = 0x08, dctr_op       = 0x09,
+       dctw_op       = 0x0a
+};
+
+/*
+ * fmt field of cop1 opcodes.
+ */
+enum cop1_fmt {
+       s_fmt, d_fmt, e_fmt, q_fmt,
+       w_fmt, l_fmt
+};
+
+/*
+ * func field of cop1 instructions using d, s or w format.
+ */
+enum cop1_sdw_func {
+       fadd_op      =  0x00, fsub_op      =  0x01,
+       fmul_op      =  0x02, fdiv_op      =  0x03,
+       fsqrt_op     =  0x04, fabs_op      =  0x05,
+       fmov_op      =  0x06, fneg_op      =  0x07,
+       froundl_op   =  0x08, ftruncl_op   =  0x09,
+       fceill_op    =  0x0a, ffloorl_op   =  0x0b,
+       fround_op    =  0x0c, ftrunc_op    =  0x0d,
+       fceil_op     =  0x0e, ffloor_op    =  0x0f,
+       fmovc_op     =  0x11, fmovz_op     =  0x12,
+       fmovn_op     =  0x13, frecip_op    =  0x15,
+       frsqrt_op    =  0x16, fcvts_op     =  0x20,
+       fcvtd_op     =  0x21, fcvte_op     =  0x22,
+       fcvtw_op     =  0x24, fcvtl_op     =  0x25,
+       fcmp_op      =  0x30
+};
+
+/*
+ * func field of cop1x opcodes (MIPS IV).
+ */
+enum cop1x_func {
+       lwxc1_op     =  0x00, ldxc1_op     =  0x01,
+       pfetch_op    =  0x07, swxc1_op     =  0x08,
+       sdxc1_op     =  0x09, madd_s_op    =  0x20,
+       madd_d_op    =  0x21, madd_e_op    =  0x22,
+       msub_s_op    =  0x28, msub_d_op    =  0x29,
+       msub_e_op    =  0x2a, nmadd_s_op   =  0x30,
+       nmadd_d_op   =  0x31, nmadd_e_op   =  0x32,
+       nmsub_s_op   =  0x38, nmsub_d_op   =  0x39,
+       nmsub_e_op   =  0x3a
+};
+
+/*
+ * func field for mad opcodes (MIPS IV).
+ */
+enum mad_func {
+       madd_op      = 0x08, msub_op      = 0x0a,
+       nmadd_op     = 0x0c, nmsub_op     = 0x0e
+};
+
+/*
+ * Damn ...  bitfields depend from byteorder :-(
+ */
+#ifdef __MIPSEB__
+struct j_format {      /* Jump format */
+       unsigned int opcode : 6;
+       unsigned int target : 26;
+};
+
+struct i_format {      /* Immediate format (addi, lw, ...) */
+       unsigned int opcode : 6;
+       unsigned int rs : 5;
+       unsigned int rt : 5;
+       signed int simmediate : 16;
+};
+
+struct u_format {      /* Unsigned immediate format (ori, xori, ...) */
+       unsigned int opcode : 6;
+       unsigned int rs : 5;
+       unsigned int rt : 5;
+       unsigned int uimmediate : 16;
+};
+
+struct c_format {      /* Cache (>= R6000) format */
+       unsigned int opcode : 6;
+       unsigned int rs : 5;
+       unsigned int c_op : 3;
+       unsigned int cache : 2;
+       unsigned int simmediate : 16;
+};
+
+struct r_format {      /* Register format */
+       unsigned int opcode : 6;
+       unsigned int rs : 5;
+       unsigned int rt : 5;
+       unsigned int rd : 5;
+       unsigned int re : 5;
+       unsigned int func : 6;
+};
+
+struct p_format {      /* Performance counter format (R10000) */
+       unsigned int opcode : 6;
+       unsigned int rs : 5;
+       unsigned int rt : 5;
+       unsigned int rd : 5;
+       unsigned int re : 5;
+       unsigned int func : 6;
+};
+
+struct f_format {      /* FPU register format */
+       unsigned int opcode : 6;
+       unsigned int : 1;
+       unsigned int fmt : 4;
+       unsigned int rt : 5;
+       unsigned int rd : 5;
+       unsigned int re : 5;
+       unsigned int func : 6;
+};
+
+struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+       unsigned int opcode : 6;
+       unsigned int fr : 5;
+       unsigned int ft : 5;
+       unsigned int fs : 5;
+       unsigned int fd : 5;
+       unsigned int func : 4;
+       unsigned int fmt : 2;
+};
+
+#elif defined(__MIPSEL__)
+
+struct j_format {      /* Jump format */
+       unsigned int target : 26;
+       unsigned int opcode : 6;
+};
+
+struct i_format {      /* Immediate format */
+       signed int simmediate : 16;
+       unsigned int rt : 5;
+       unsigned int rs : 5;
+       unsigned int opcode : 6;
+};
+
+struct u_format {      /* Unsigned immediate format */
+       unsigned int uimmediate : 16;
+       unsigned int rt : 5;
+       unsigned int rs : 5;
+       unsigned int opcode : 6;
+};
+
+struct c_format {      /* Cache (>= R6000) format */
+       unsigned int simmediate : 16;
+       unsigned int cache : 2;
+       unsigned int c_op : 3;
+       unsigned int rs : 5;
+       unsigned int opcode : 6;
+};
+
+struct r_format {      /* Register format */
+       unsigned int func : 6;
+       unsigned int re : 5;
+       unsigned int rd : 5;
+       unsigned int rt : 5;
+       unsigned int rs : 5;
+       unsigned int opcode : 6;
+};
+
+struct p_format {      /* Performance counter format (R10000) */
+       unsigned int func : 6;
+       unsigned int re : 5;
+       unsigned int rd : 5;
+       unsigned int rt : 5;
+       unsigned int rs : 5;
+       unsigned int opcode : 6;
+};
+
+struct f_format {      /* FPU register format */
+       unsigned int func : 6;
+       unsigned int re : 5;
+       unsigned int rd : 5;
+       unsigned int rt : 5;
+       unsigned int fmt : 4;
+       unsigned int : 1;
+       unsigned int opcode : 6;
+};
+
+struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+       unsigned int fmt : 2;
+       unsigned int func : 4;
+       unsigned int fd : 5;
+       unsigned int fs : 5;
+       unsigned int ft : 5;
+       unsigned int fr : 5;
+       unsigned int opcode : 6;
+};
+
+#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
+#endif
+
+union mips_instruction {
+       unsigned int word;
+       unsigned short halfword[2];
+       unsigned char byte[4];
+       struct j_format j_format;
+       struct i_format i_format;
+       struct u_format u_format;
+       struct c_format c_format;
+       struct r_format r_format;
+       struct f_format f_format;
+        struct ma_format ma_format;
+};
+
+#endif /* __ASM_MIPS_INST_H */
index 222c3676fb0fce4220bd97437a8d14b803bd6be0..be0d068a49ac1447451b2e5aac72ef362d2a123e 100644 (file)
@@ -1,14 +1,21 @@
 #ifndef __ASM_MIPS_IO_H
 #define __ASM_MIPS_IO_H
 
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
+
 #include <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
  *
@@ -33,6 +40,7 @@
  * 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..
@@ -113,10 +187,10 @@ __OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (PORT_BASE)); \
 extern __inline__ t __in##s(unsigned int port) { t _v;
 
 /*
- * Useless nops will be removed by the assembler
+ * Required nops will be inserted by the assembler
  */
 #define __IN2(m) \
-__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\tnop"
+__asm__ __volatile__ ("l" #m "\t%0,%1(%2)"
 
 #define __IN(t,m,s) \
 __IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
@@ -128,10 +202,11 @@ __IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (PORT_BASE)); SLOW_DOWN_
 extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
 
 #define __INS2(m) \
+if (count) \
 __asm__ __volatile__ ( \
        ".set\tnoreorder\n\t" \
        ".set\tnoat\n" \
-       "1:\tl" #m "u\t$1,%4(%5)\n\t" \
+       "1:\tl" #m "\t$1,%4(%5)\n\t" \
        "subu\t%1,1\n\t" \
        "s" #m "\t$1,(%0)\n\t" \
        "bne\t$0,%1,1b\n\t" \
@@ -153,14 +228,15 @@ __INS1(s##c) __INS2(m) \
 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"
 
index af6fd89cc11cdfe35fdf57a4c969893426466385..360b22ce337e26a17bf07dc55399b4ef37129e81 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * Linux ioctl() stuff.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_IOCTL_H
 #define __ASM_MIPS_IOCTL_H
 
index 63f7e826863ba3c013b6ce80d9b8c5a507b1bac9..54512f8d8f85010784defcd3671c284a887427ab 100644 (file)
@@ -1,8 +1,21 @@
+/*
+ * ioctls for Linux/MIPS.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_IOCTLS_H
 #define __ASM_MIPS_IOCTLS_H
 
 #include <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 */
diff --git a/include/asm-mips/ipc.h b/include/asm-mips/ipc.h
new file mode 100644 (file)
index 0000000..3288c1e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_MIPS_IPC_H
+#define __ASM_MIPS_IPC_H
+
+/* 
+ * These are used to wrap system calls on MIPS.
+ *
+ * See arch/mips/kernel/sysmips.c for ugly details..
+ * FIXME: split up into ordinary syscalls ...
+ */
+struct ipc_kludge {
+       struct msgbuf *msgp;
+       long msgtyp;
+};
+
+#define SEMOP           1
+#define SEMGET          2
+#define SEMCTL          3
+#define MSGSND         11
+#define MSGRCV         12
+#define MSGGET         13
+#define MSGCTL         14
+#define SHMAT          21
+#define SHMDT          22
+#define SHMGET         23
+#define SHMCTL         24
+
+#define IPCCALL(version,op)    ((version)<<16 | (op))
+
+#endif /* __ASM_MIPS_IPC_H */
index bce4feabb4470793bf0acb7d8bcd46ec205722c8..b09ca61a4b00efaf0a2f1f14ea0312bf62a57d06 100644 (file)
 /*
  * 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);
 
index c51ad091728a93c9ccbf847e4f60b0488ff51aaa..41ab8963485a3ce78111da01f8c2c4970e11b0c2 100644 (file)
@@ -9,7 +9,6 @@
  *
  * This file is a mess. It really needs some reorganisation!
  */
-
 #ifndef __ASM_MIPS_JAZZ_H 
 #define __ASM_MIPS_JAZZ_H 
 
@@ -86,6 +85,16 @@ extern __inline__ void pica_set_led(unsigned int bits)
 
 #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
@@ -196,7 +205,7 @@ typedef struct {
  */
 #define JAZZ_TIMER_IRQ          0
 #define JAZZ_KEYBOARD_IRQ       1
-#define JAZZ_ETHERNET_IRQ       2 /* 15 */
+#define JAZZ_ETHERNET_IRQ       13
 #define JAZZ_SERIAL1_IRQ        3
 #define JAZZ_SERIAL2_IRQ        4
 #define JAZZ_PARALLEL_IRQ       5
@@ -245,66 +254,63 @@ typedef struct {
 #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 */
index 582acdc83fcd28b2e9efefd979738b0149484039..c7f1730cf4f588d06d444d253f274efe6cbf4268 100644 (file)
@@ -1,14 +1,12 @@
 /*
  * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
  */
-
-#ifndef __ASM_JAZZDMA_H
-#define __ASM_JAZZDMA_H
+#ifndef __ASM_MIPS_JAZZDMA_H
+#define __ASM_MIPS_JAZZDMA_H
 
 /*
  * Prototypes and macros
  */
-
 unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end);
 unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
 int vdma_free(unsigned long laddr);
@@ -76,8 +74,9 @@ typedef volatile struct VDMA_PGTBL_ENTRY
 #define R4030_MEM_INTR           (1<<9)
 #define R4030_ADDR_INTR          (1<<10)
 
-/* channel mode register bits */
-
+/*
+ * Channel mode register bits
+ */
 #define R4030_MODE_ATIME_40      (0) /* device access time on remote bus */
 #define R4030_MODE_ATIME_80      (1)
 #define R4030_MODE_ATIME_120     (2)
@@ -93,4 +92,4 @@ typedef volatile struct VDMA_PGTBL_ENTRY
 #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 */
index 9c9f3a41a51cecff68d2427fd782a36b3fe747e8..685b04be1c04718aa6973bef29c7edaa0f124c41 100644 (file)
@@ -1,20 +1,22 @@
 /*
- *  linux/include/asm-mips/keyboard.h
+ * CPU specific parts of the keyboard driver
  *
- *  Created 3 Nov 1996 by Geert Uytterhoeven
- */
-
-/*
- *  This file contains the mips architecture specific keyboard definitions
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This file is a mess.  Put on your peril sensitive glasses.
+ *
+ * $Id: keyboard.h,v 1.4 1997/06/16 00:31:46 ralf Exp $
  */
-
-#ifndef __ASMMIPS_KEYBOARD_H
-#define __ASMMIPS_KEYBOARD_H
+#ifndef __ASM_MIPS_KEYBOARD_H
+#define __ASM_MIPS_KEYBOARD_H
 
 #ifdef __KERNEL__
 
-#define KEYBOARD_IRQ                   1
-#define DISABLE_KBD_DURING_INTERRUPTS  0
+#include <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);
@@ -33,8 +35,203 @@ extern void pckbd_init_hw(void);
 #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 */
index f838a525aadbedc53153463d63e53035276f011e..0e27005263057bfbdf9848f82b49a76df02109d8 100644 (file)
@@ -9,7 +9,7 @@
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)    (0x70 + (x))
-#define RTC_ALWAYS_BCD 1
+#define RTC_ALWAYS_BCD 0       /* RTC operates in binary mode */
 #endif
 
 /*
  * 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 */
index 1cbf7662e61c892779c3c9d4881a48bd677e7223..bb9907bc1936988b48f668fc39054833e20a2af3 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_MIPSCONFIG_H
 #define __ASM_MIPS_MIPSCONFIG_H
  * Must be a value that can be load with a lui instruction.
  */
 #ifndef PORT_BASE
-#define PORT_BASE              0xe2000000
+#if !defined (__LANGUAGE_ASSEMBLY__)
+extern unsigned long port_base;
+#endif
+#define PORT_BASE port_base
 #endif
 
-/*
- * Pagetables are 4MB mapped at 0xe4000000
- * Must be a value that can be loaded with a single instruction.
- */
-#define TLBMAP                 0xe4000000
-
-/*
- * The virtual address where we'll map the pagetables
- * For a base address of 0xe3000000 this is 0xe338c000
- * For a base address of 0xe4000000 this is 0xe4390000
- * FIXME: Gas computes the following expression with signed
- *        shift and therefore false
-#define TLB_ROOT               (TLBMAP + (TLBMAP >> (12-2)))
- */
-#define TLB_ROOT               0xe4390000
-
-/*
- * Use this to activate extra TLB error checking
- */
-#define CONF_DEBUG_TLB
-
-/*
- * Use this to activate extra TLB profiling code
- * (currently not implemented)
- */
-#undef CONF_PROFILE_TLB
-
-/*
- * Disable all caching.  Useful to find trouble with caches in drivers.
- */
-#undef CONF_DISABLE_KSEG0_CACHING
+/* Pgdir is 1 page mapped at 0xff800000. */
+#define TLBMAP                 0xff800000
 
-/*
- * Set this to one to enable additional vdma debug code.
- */
-#define CONF_DEBUG_VDMA 0
+/* The virtual address where we'll map the pgdir. */
+#define TLB_ROOT               0xff000000
 
 #endif /* __ASM_MIPS_MIPSCONFIG_H */
diff --git a/include/asm-mips/mipsprom.h b/include/asm-mips/mipsprom.h
new file mode 100644 (file)
index 0000000..ce7cff7
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __ASM_MIPS_PROM_H
+#define __ASM_MIPS_PROM_H
+
+#define PROM_RESET             0
+#define PROM_EXEC              1
+#define PROM_RESTART           2
+#define PROM_REINIT            3
+#define PROM_REBOOT            4
+#define PROM_AUTOBOOT          5
+#define PROM_OPEN              6
+#define PROM_READ              7
+#define PROM_WRITE             8
+#define PROM_IOCTL             9
+#define PROM_CLOSE             10
+#define PROM_GETCHAR           11
+#define PROM_PUTCHAR           12
+#define PROM_SHOWCHAR          13      /* XXX */
+#define PROM_GETS              14      /* XXX */
+#define PROM_PUTS              15      /* XXX */
+#define PROM_PRINTF            16      /* XXX */
+
+/* What are these for? */
+#define PROM_INITPROTO         17      /* XXX */
+#define PROM_PROTOENABLE       18      /* XXX */
+#define PROM_PROTODISABLE      19      /* XXX */
+#define PROM_GETPKT            20      /* XXX */
+#define PROM_PUTPKT            21      /* XXX */
+
+/* More PROM shit.  Probably has to do with VME RMW cycles??? */
+#define PROM_ORW_RMW           22      /* XXX */
+#define PROM_ORH_RMW           23      /* XXX */
+#define PROM_ORB_RMW           24      /* XXX */
+#define PROM_ANDW_RMW          25      /* XXX */
+#define PROM_ANDH_RMW          26      /* XXX */
+#define PROM_ANDB_RMW          27      /* XXX */
+
+/* Cache handling stuff */
+#define PROM_FLUSHCACHE                28      /* XXX */
+#define PROM_CLEARCACHE                29      /* XXX */
+
+/* Libc alike stuff */
+#define PROM_SETJMP            30      /* XXX */
+#define PROM_LONGJMP           31      /* XXX */
+#define PROM_BEVUTLB           32      /* XXX */
+#define PROM_GETENV            33      /* XXX */
+#define PROM_SETENV            34      /* XXX */
+#define PROM_ATOB              35      /* XXX */
+#define PROM_STRCMP            36      /* XXX */
+#define PROM_STRLEN            37      /* XXX */
+#define PROM_STRCPY            38      /* XXX */
+#define PROM_STRCAT            39      /* XXX */
+
+/* Misc stuff */
+#define PROM_PARSER            40      /* XXX */
+#define PROM_RANGE             41      /* XXX */
+#define PROM_ARGVIZE           42      /* XXX */
+#define PROM_HELP              43      /* XXX */
+
+/* Entry points for some PROM commands */
+#define PROM_DUMPCMD           44      /* XXX */
+#define PROM_SETENVCMD         45      /* XXX */
+#define PROM_UNSETENVCMD       46      /* XXX */
+#define PROM_PRINTENVCMD       47      /* XXX */
+#define PROM_BEVEXCEPT         48      /* XXX */
+#define PROM_ENABLECMD         49      /* XXX */
+#define PROM_DISABLECMD                50      /* XXX */
+
+#define PROM_CLEARNOFAULT      51      /* XXX */
+#define PROM_NOTIMPLEMENT      52      /* XXX */
+
+#define PROM_NV_GET            53      /* XXX */
+#define PROM_NV_SET            54      /* XXX */
+
+#endif /* __ASM_MIPS_PROM_H */
index 96b9ba21325b929537db16bb3070af6b9d6930ed..bf2340305d3f45fc0a3200ad532aea88e842e171 100644 (file)
@@ -5,17 +5,18 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  */
-
 #ifndef __ASM_MIPS_MIPSREGS_H
 #define __ASM_MIPS_MIPSREGS_H
 
+#include <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__(                                   \
@@ -176,9 +183,14 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
 /*
  * Inline code for use of the ll and sc instructions
  *
- * FIXME: This instruction is only available on MIPS ISA >=3.
+ * FIXME: This instruction is only available on MIPS ISA >=2.
  * Since these operations are only being used for atomic operations
  * the easiest workaround for the R[23]00 is to disable interrupts.
+ * This fails for R3000 SMP machines which use that many different
+ * technologies as replacement that it is difficult to create even
+ * just a hook for for all machines to hook into.  The only good
+ * thing is that there is currently no R3000 SMP machine on the
+ * Linux/MIPS target list ...
  */
 #define load_linked(addr)                                       \
 ({                                                              \
@@ -187,7 +199,7 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
        __asm__ __volatile__(                                   \
        "ll\t%0,(%1)"                                           \
        : "=r" (__res)                                          \
-       : "r" ((unsigned int) (addr)));                         \
+       : "r" ((unsigned long) (addr)));                        \
                                                                 \
        __res;                                                  \
 })
@@ -205,35 +217,53 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
 })
 
 /*
- * 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.
@@ -265,4 +295,77 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
 #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 */
index f37a215c66b80720b5a7f4751727087b30cd9a65..f95aec1e66bc4ac9681a19d7ec8c31c46bd86e75 100644 (file)
@@ -36,6 +36,7 @@
 #define MAP_AUTORSRV   0x100           /* Logical swap reserved on demand */
 
 /* These are linux-specific */
+#define MAP_NORESERVE  0x0400          /* don't check for reservations */
 #define MAP_ANONYMOUS  0x0800          /* don't use a file */
 #define MAP_GROWSDOWN  0x1000          /* stack-like segment */
 #define MAP_DENYWRITE  0x2000          /* ETXTBSY */
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
new file mode 100644 (file)
index 0000000..87b1279
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Switch a MMU context.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_MMU_CONTEXT_H
+#define __ASM_MIPS_MMU_CONTEXT_H
+
+#define MAX_ASID 255
+
+extern unsigned long asid_cache;
+
+#define ASID_VERSION_SHIFT 16
+#define ASID_VERSION_MASK  ((~0UL) << ASID_VERSION_SHIFT)
+#define ASID_FIRST_VERSION (1UL << ASID_VERSION_SHIFT)
+
+extern inline void get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+       /* check if it's legal.. */
+       if ((asid & ~ASID_VERSION_MASK) > MAX_ASID) {
+               /* start a new version, invalidate all old asid's */
+               flush_tlb_all();
+               asid = (asid & ASID_VERSION_MASK) + ASID_FIRST_VERSION;
+               if (!asid)
+                       asid = ASID_FIRST_VERSION;
+       }
+       asid_cache = asid + 1;
+       mm->context = asid;                      /* full version + asid */
+}
+
+extern inline void get_mmu_context(struct task_struct *p)
+{
+       struct mm_struct *mm = p->mm;
+
+       if (mm) {
+               unsigned long asid = asid_cache;
+               /* Check if our ASID is of an older version and thus invalid */
+               if ((mm->context ^ asid) & ASID_VERSION_MASK)
+                       get_new_mmu_context(mm, asid);
+       }
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+extern inline void init_new_context(struct mm_struct *mm)
+{
+       mm->context = 0;
+}
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+extern inline void destroy_context(struct mm_struct *mm)
+{
+       mm->context = 0;
+}
+
+#endif /* __ASM_MIPS_MMU_CONTEXT_H */
diff --git a/include/asm-mips/namei.h b/include/asm-mips/namei.h
new file mode 100644 (file)
index 0000000..0ff96ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-mips/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+#ifndef __ASM_MIPS_NAMEI_H
+#define __ASM_MIPS_NAMEI_H
+
+#include <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(&current->fs->root->i_count);
+       error = __namei(NAM_FOLLOW_LINK, IRIX32_EMUL, current->fs->root,
+                       buf, NULL, &base, NULL, NULL, NULL);
+       if (error)
+               return error;
+
+       error = __namei(retrieve_mode, name, base, buf, res_dir, res_inode,
+                       last_name, last_entry, last_error);
+       if (error)
+               return error;
+
+       return 0;
+}
+
+#else /* !defined(CONFIG_BINFMT_IRIX) */
+
+#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \
+                      last_name, last_entry, last_error) 1
+
+#endif /* !defined(CONFIG_BINFMT_IRIX) */
+
+#endif /* __ASM_MIPS_NAMEI_H */
diff --git a/include/asm-mips/offset.h b/include/asm-mips/offset.h
new file mode 100644 (file)
index 0000000..0f6e63a
--- /dev/null
@@ -0,0 +1,88 @@
+/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
+
+#ifndef _MIPS_OFFSET_H
+#define _MIPS_OFFSET_H
+
+/* MIPS pt_regs offsets. */
+#define PT_R0     24
+#define PT_R1     28
+#define PT_R2     32
+#define PT_R3     36
+#define PT_R4     40
+#define PT_R5     44
+#define PT_R6     48
+#define PT_R7     52
+#define PT_R8     56
+#define PT_R9     60
+#define PT_R10    64
+#define PT_R11    68
+#define PT_R12    72
+#define PT_R13    76
+#define PT_R14    80
+#define PT_R15    84
+#define PT_R16    88
+#define PT_R17    92
+#define PT_R18    96
+#define PT_R19    100
+#define PT_R20    104
+#define PT_R21    108
+#define PT_R22    112
+#define PT_R23    116
+#define PT_R24    120
+#define PT_R25    124
+#define PT_R26    128
+#define PT_R27    132
+#define PT_R28    136
+#define PT_R29    140
+#define PT_R30    144
+#define PT_R31    148
+#define PT_LO     152
+#define PT_HI     156
+#define PT_OR2    160
+#define PT_OR7    164
+#define PT_EPC    168
+#define PT_BVADDR 172
+#define PT_STATUS 176
+#define PT_CAUSE  180
+#define PT_SIZE   184
+
+/* MIPS task_struct offsets. */
+#define TASK_STATE         0
+#define TASK_COUNTER       4
+#define TASK_PRIORITY      8
+#define TASK_SIGNAL        12
+#define TASK_BLOCKED       16
+#define TASK_FLAGS         20
+#define TASK_MM            912
+
+/* MIPS specific thread_struct offsets. */
+#define THREAD_REG16   544
+#define THREAD_REG17   548
+#define THREAD_REG18   552
+#define THREAD_REG19   556
+#define THREAD_REG20   560
+#define THREAD_REG21   564
+#define THREAD_REG22   568
+#define THREAD_REG23   572
+#define THREAD_REG28   576
+#define THREAD_REG29   580
+#define THREAD_REG30   584
+#define THREAD_REG31   588
+#define THREAD_STATUS  592
+#define THREAD_FPU     600
+#define THREAD_BVADDR  864
+#define THREAD_ECODE   868
+#define THREAD_TRAPNO  872
+#define THREAD_KSP     876
+#define THREAD_PGDIR   880
+#define THREAD_MFLAGS  884
+#define THREAD_CURDS   888
+#define THREAD_TRAMP   892
+#define THREAD_OLDCTX  896
+
+/* Linux mm_struct offsets. */
+#define MM_COUNT      12
+#define MM_PGD        8
+#define MM_CONTEXT    28
+
+#endif /* !(_MIPS_OFFSET_H) */
index 59a9dfa5d6cfe1fb886434a8ffdacb042ec4cf49..ba42d3baa04376b39ffb5ccd4a801f5f26b89587 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * Definitions for page handling
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_PAGE_H
 #define __ASM_MIPS_PAGE_H
 
@@ -12,6 +21,9 @@
 
 #ifndef __LANGUAGE_ASSEMBLY__
 
+extern void (*clear_page)(unsigned long page);
+extern void (*copy_page)(unsigned long to, unsigned long from);
+
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
@@ -52,51 +64,21 @@ typedef unsigned long pgprot_t;
 
 #endif /* !defined (STRICT_MM_TYPECHECKS) */
 
-/*
- * We need a special version of copy_page that can handle virtual caches.
- * While we're at tweaking with caches we can use that to make it even
- * faster.  The R10000 accelerated caching mode will further accelerate it.
- */
-extern void __copy_page(unsigned long from, unsigned long to);
-#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
-
 #endif /* __LANGUAGE_ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
-/* This handles the memory map */
-#if __mips == 3
 /*
- * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent)
- * Pagetables are at  XKPHYS + 0x1000000000000000 (uncached)
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
  */
-#define PAGE_OFFSET    0x9800000000000000UL
-#define PT_OFFSET      0x9000000000000000UL
-#define MAP_MASK        0x07ffffffffffffffUL
-#else
-/*
- * We handle pages at KSEG0 (cachable, noncoherent)
- * Pagetables are at  KSEG1 (uncached)
- */
-#define PAGE_OFFSET    0x80000000
-#define PT_OFFSET      0xa0000000
-#define MAP_MASK        0x1fffffff
-#endif
-
+#define PAGE_OFFSET    0x80000000UL
+#define __pa(x)                ((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x)                ((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define MAP_MASK        0x1fffffffUL
 #define MAP_NR(addr)   ((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT)
 
-#ifndef __LANGUAGE_ASSEMBLY__
-
-extern unsigned long page_colour_mask;
-
-extern inline unsigned long
-page_colour(unsigned long page)
-{
-       return page & page_colour_mask;
-}
-
-#endif /* defined (__LANGUAGE_ASSEMBLY__) */
 #endif /* defined (__KERNEL__) */
 
 #endif /* __ASM_MIPS_PAGE_H */
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
new file mode 100644 (file)
index 0000000..a506e4b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Declarations for the MIPS specific implementation of the PCI BIOS32 services.
+ */
+#ifndef __ASM_MIPS_PCI_H
+#define __ASM_MIPS_PCI_H
+
+extern unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end);
+extern unsigned long (*_pcibios_fixup) (unsigned long memory_start,
+                                        unsigned long memory_end);
+extern int (*_pcibios_read_config_byte) (unsigned char bus,
+                                         unsigned char dev_fn,
+                                         unsigned char where,
+                                         unsigned char *val);
+extern int (*_pcibios_read_config_word) (unsigned char bus,
+                                         unsigned char dev_fn,
+                                         unsigned char where,
+                                         unsigned short *val);
+extern int (*_pcibios_read_config_dword) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned int *val);
+extern int (*_pcibios_write_config_byte) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned char val);
+extern int (*_pcibios_write_config_word) (unsigned char bus,
+                                          unsigned char dev_fn,
+                                          unsigned char where,
+                                          unsigned short val);
+extern int (*_pcibios_write_config_dword) (unsigned char bus,
+                                           unsigned char dev_fn,
+                                           unsigned char where,
+                                           unsigned int val);
+
+#endif /* __ASM_MIPS_PCI_H */
index 1b2db54477b13f152db40a45581f8ba5914e74d1..c6bb9b2de2d637a2d4e126ee44881e3b69d16171 100644 (file)
@@ -1,63 +1,49 @@
 #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__) */
 
@@ -71,8 +57,7 @@ extern void __copy_page(unsigned long from, unsigned long to);
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
-/*
- * entries per page directory level: we use two-level, so
+/* Entries per page directory level: we use two-level, so
  * we don't really have any PMD directory physically.
  */
 #define PTRS_PER_PTE   1024
@@ -82,22 +67,32 @@ extern void __copy_page(unsigned long from, unsigned long to);
 #define VMALLOC_START     KSEG2
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 
-/*
- * Note that we shift the lower 32bits of each EntryLo[01] entry
+/* Note that we shift the lower 32bits of each EntryLo[01] entry
  * 6 bits to the left. That way we can convert the PFN into the
  * physical address by a single 'and' operation and gain 6 additional
  * bits for storing information which isn't present in a normal
  * MIPS page table.
- * Since the Mips has chosen some quite misleading names for the
- * valid and dirty bits they're defined here but only their synonyms
- * will be used.
+ *
+ * Similar to the Alpha port, we need to keep track of the ref
+ * and mod bits in software.  We have a software "yeah you can read
+ * from this page" bit, and a hardware one which actually lets the
+ * process read from the page.  On the same token we have a software
+ * writable bit and the real hardware one which actually lets the
+ * process write to the page, this keeps a mod bit via the hardware
+ * dirty bit.
+ *
+ * Certain revisions of the R4000 and R5000 have a bug where if a
+ * certain sequence occurs in the last 3 instructions of an executable
+ * page, and the following page is not mapped, the cpu can do
+ * unpredictable things.  The code (when it is written) to deal with
+ * this problem will be in the update_mmu_cache() code for the r4k.
  */
 #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
-#define _PAGE_COW                   (1<<1)  /* implemented in software */
-#define _PAGE_READ                  (1<<2)  /* implemented in software */
-#define _PAGE_WRITE                 (1<<3)  /* implemented in software */
-#define _PAGE_ACCESSED              (1<<4)  /* implemented in software */
-#define _PAGE_MODIFIED              (1<<5)  /* implemented in software */
+#define _PAGE_READ                  (1<<1)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<2)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<3)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<4)  /* implemented in software */
+#define _PAGE_R4KBUG                (1<<5)  /* workaround for r4k bug  */
 #define _PAGE_GLOBAL                (1<<6)
 #define _PAGE_VALID                 (1<<7)
 #define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
@@ -116,16 +111,15 @@ extern void __copy_page(unsigned long from, unsigned long to);
 #define __READABLE     (_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED)
 #define __WRITEABLE    (_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED)
 
-#define _PAGE_TABLE    (_PAGE_PRESENT | __READABLE | __WRITEABLE | \
-                       _PAGE_DIRTY | _CACHE_UNCACHED)
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
+#define _PAGE_CHG_MASK  (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK)
 
-#define PAGE_NONE      __pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED)
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                        _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
                        _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_READ | \
                        _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | __READABLE | \
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_READ | \
                        _CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
                        _CACHE_CACHABLE_NONCOHERENT)
@@ -155,9 +149,6 @@ extern void __copy_page(unsigned long from, unsigned long to);
 
 #if !defined (__LANGUAGE_ASSEMBLY__)
 
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
-
 /*
  * BAD_PAGETABLE is used when we need a bogus page-table, while
  * BAD_PAGE is used for a bogus page.
@@ -166,13 +157,15 @@ extern unsigned long pg0[1024];
  * for zero-mapped memory areas etc..
  */
 extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
+extern pte_t *__bad_pagetable(void);
 
 extern unsigned long __zero_page(void);
 
+extern unsigned long empty_zero_page[1024];
+
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
+#define ZERO_PAGE ((unsigned long)empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR                   (8*sizeof(unsigned long))
@@ -181,31 +174,19 @@ extern unsigned long __zero_page(void);
 #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)];
 
 /*
@@ -213,39 +194,60 @@ 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
@@ -255,36 +257,41 @@ extern inline void pmd_reuse(pmd_t * pmdp)        { }
 extern inline int pgd_none(pgd_t pgd)          { return 0; }
 extern inline int pgd_bad(pgd_t pgd)           { return 0; }
 extern inline int pgd_present(pgd_t pgd)       { return 1; }
-extern inline int pgd_inuse(pgd_t * pgdp)      { return mem_map[MAP_NR(pgdp)].reserved; }
-extern inline void pgd_clear(pgd_t * pgdp)     { }
+extern inline void pgd_clear(pgd_t *pgdp)      { }
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_WRITE; }
-extern inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_MODIFIED; }
-extern inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_cow(pte_t pte)           { return pte_val(pte) & _PAGE_COW; }
+extern inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
 
 extern inline pte_t pte_wrprotect(pte_t pte)
 {
        pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
        return pte;
 }
+
 extern inline pte_t pte_rdprotect(pte_t pte)
 {
-       pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+       pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+       return pte;
 }
-extern inline pte_t pte_exprotect(pte_t pte)
+
+extern inline pte_t pte_mkclean(pte_t pte)
 {
-       pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+       pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+       return pte;
 }
-extern inline pte_t pte_mkclean(pte_t pte)     { pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); return pte; }
-extern inline pte_t pte_mkold(pte_t pte)       { pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); return pte; }
-extern inline pte_t pte_uncow(pte_t pte)       { pte_val(pte) &= ~_PAGE_COW; return pte; }
+
+extern inline pte_t pte_mkold(pte_t pte)
+{
+       pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE);
+       return pte;
+}
+
 extern inline pte_t pte_mkwrite(pte_t pte)
 {
        pte_val(pte) |= _PAGE_WRITE;
@@ -292,6 +299,7 @@ extern inline pte_t pte_mkwrite(pte_t pte)
                pte_val(pte) |= _PAGE_SILENT_WRITE;
        return pte;
 }
+
 extern inline pte_t pte_mkread(pte_t pte)
 {
        pte_val(pte) |= _PAGE_READ;
@@ -299,13 +307,7 @@ extern inline pte_t pte_mkread(pte_t pte)
                pte_val(pte) |= _PAGE_SILENT_READ;
        return pte;
 }
-extern inline pte_t pte_mkexec(pte_t pte)
-{
-       pte_val(pte) |= _PAGE_READ;
-       if (pte_val(pte) & _PAGE_ACCESSED)
-               pte_val(pte) |= _PAGE_SILENT_READ;
-       return pte;
-}
+
 extern inline pte_t pte_mkdirty(pte_t pte)
 {
        pte_val(pte) |= _PAGE_MODIFIED;
@@ -313,257 +315,453 @@ extern inline pte_t pte_mkdirty(pte_t pte)
                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__) */
 
diff --git a/include/asm-mips/poll.h b/include/asm-mips/poll.h
new file mode 100644 (file)
index 0000000..12c1a5e
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_MIPS_POLL_H
+#define __ASM_MIPS_POLL_H
+
+#define POLLIN         0x0001
+#define POLLPRI                0x0002
+#define POLLOUT                0x0004
+
+#define POLLERR                0x0008
+#define POLLHUP                0x0010
+#define POLLNVAL       0x0020
+
+#define POLLRDNORM     0x0040
+#define POLLRDBAND     0x0080
+#define POLLWRNORM     POLLOUT
+#define POLLWRBAND     0x0100
+
+/* XXX This one seems to be more-or-less nonstandard.  */
+#define POLLMSG                0x0400
+
+struct pollfd {
+       int fd;
+       short events;
+       short revents;
+};
+
+#endif /* __ASM_MIPS_POLL_H */
diff --git a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h
new file mode 100644 (file)
index 0000000..deffcf2
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * POSIX types
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ARCH_MIPS_POSIX_TYPES_H
+#define __ARCH_MIPS_POSIX_TYPES_H
+
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <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 */
index 7ac70a6a56ead0c696d6a8df02773cb04993df20..c4c0e849b5437dbc16303b99228df8b85cbdb932 100644 (file)
@@ -3,8 +3,8 @@
  *
  * Copyright (C) 1994  Waldorf Electronics
  * written by Ralf Baechle
+ * Modified further for R[236]000 compatibility by Paul M. Antoine
  */
-
 #ifndef __ASM_MIPS_PROCESSOR_H
 #define __ASM_MIPS_PROCESSOR_H
 
@@ -19,9 +19,6 @@
  */
 extern char wait_available;            /* only available on R4[26]00 */
 
-extern atomic_t intr_count;
-extern unsigned long event;
-
 /*
  * Bus types (default is ISA, but people can check others with these..)
  * MCA_bus hardcoded to 0 for now.
@@ -41,7 +38,9 @@ extern int EISA_bus;
 
 /*
  * User space process size: 2GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
+ * so don't change it unless you know what you are doing.  TASK_SIZE
+ * for a 64 bit kernel expandable to 8192EB, of which the current MIPS
+ * implementations will "only" be able to use 1TB ...
  */
 #define TASK_SIZE      (0x80000000UL)
 
@@ -67,7 +66,7 @@ struct mips_fpu_hard_struct {
  */
 struct mips_fpu_soft_struct {
        long    dummy;
-       };
+};
 
 union mips_fpu_union {
         struct mips_fpu_hard_struct hard;
@@ -82,62 +81,33 @@ union mips_fpu_union {
  * If you change thread_struct remember to change the #defines below too!
  */
 struct thread_struct {
-        /*
-         * saved main processor registers
-         */
-        unsigned long   reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
-        unsigned long                               reg28, reg29, reg30, reg31;
-       /*
-        * saved cp0 stuff
-        */
+        /* Saved main processor registers. */
+        unsigned long reg16 __attribute__ ((aligned (8)));
+       unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+        unsigned long reg28, reg29, reg30, reg31;
+
+       /* Saved cp0 stuff. */
        unsigned long cp0_status;
-       /*
-        * saved fpu/fpu emulator stuff
-        */
-       union mips_fpu_union fpu;
-       /*
-        * Other stuff associated with the thread
-        */
+
+       /* Saved fpu/fpu emulator stuff. */
+       union mips_fpu_union fpu __attribute__ ((aligned (8)));
+
+       /* Other stuff associated with the thread. */
        unsigned long cp0_badvaddr;
        unsigned long error_code;
        unsigned long trap_no;
-       unsigned long ksp;              /* Top of kernel stack   */
-       unsigned long pg_dir;           /* L1 page table pointer */
-#define MF_FIXADE 1
+       unsigned long ksp;                      /* Top of kernel stack   */
+       unsigned long pg_dir;                   /* used in tlb refill    */
+#define MF_FIXADE 1                    /* Fix address errors in software */
+#define MF_LOGADE 2                    /* Log address errors to syslog */
        unsigned long mflags;
+       int current_ds;
+       unsigned long irix_trampoline;  /* Wheee... */
+       unsigned long irix_oldctx;
 };
 
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
-/*
- * If you change the #defines remember to change thread_struct above too!
- */
-#define TOFF_REG16             0
-#define TOFF_REG17             (TOFF_REG16+4)
-#define TOFF_REG18             (TOFF_REG17+4)
-#define TOFF_REG19             (TOFF_REG18+4)
-#define TOFF_REG20             (TOFF_REG19+4)
-#define TOFF_REG21             (TOFF_REG20+4)
-#define TOFF_REG22             (TOFF_REG21+4)
-#define TOFF_REG23             (TOFF_REG22+4)
-#define TOFF_REG28             (TOFF_REG23+4)
-#define TOFF_REG29             (TOFF_REG28+4)
-#define TOFF_REG30             (TOFF_REG29+4)
-#define TOFF_REG31             (TOFF_REG30+4)
-#define TOFF_CP0_STATUS                (TOFF_REG31+4)
-/*
- * Pad for 8 byte boundary!
- */
-#define TOFF_FPU               (((TOFF_CP0_STATUS+4)+(8-1))&~(8-1))
-#define TOFF_CP0_BADVADDR      (TOFF_FPU+264)
-#define TOFF_ERROR_CODE                (TOFF_CP0_BADVADDR+4)
-#define TOFF_TRAP_NO           (TOFF_ERROR_CODE+4)
-#define TOFF_KSP               (TOFF_TRAP_NO+4)
-#define TOFF_PG_DIR            (TOFF_KSP+4)
-#define TOFF_MFLAGS            (TOFF_PG_DIR+4)
-
-#if !defined (__LANGUAGE_ASSEMBLY__)
-
 #define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
                     VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
 
@@ -156,81 +126,79 @@ struct thread_struct {
         */ \
        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 */
index a297a1c8a882066d70bea3f6e12a7d8946795020..ebe4cf888b2741a4c7df6a6b19117af67f52fefa 100644 (file)
@@ -5,8 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Waldorf GMBH
- * written by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
  *
  * Machine dependent structs and defines to help the user use
  * the ptrace system call.
 #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 */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
new file mode 100644 (file)
index 0000000..ebacf77
--- /dev/null
@@ -0,0 +1,1025 @@
+/* $Id: r4kcache.h,v 1.1 1997/06/06 09:39:42 ralf Exp $
+ * r4kcache.h: Inline assembly cache operations.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_R4KCACHE_H
+#define _MIPS_R4KCACHE_H
+
+#include <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) */
diff --git a/include/asm-mips/reboot.h b/include/asm-mips/reboot.h
new file mode 100644 (file)
index 0000000..930b498
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 by Ralf Baechle
+ *
+ * Declare variables for rebooting.
+ */
+#ifndef __ASM_MIPS_REBOOT_H
+#define __ASM_MIPS_REBOOT_H
+
+void (*_machine_restart)(char *command);
+void (*_machine_halt)(void);
+void (*_machine_power_off)(void);
+
+#endif /* __ASM_MIPS_REBOOT_H */
index 701386d730e8dbaa14791611b56859435299e26e..5fd97c23cd0a7016a991873d482b5a872b383dab 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Makefile for MIPS Linux main source directory
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * 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 */
index a214aa20701e842be7d12d19fdf7b15e1d20b0f8..16c83544d6331ed93731c97a3de3e7b21faf5f5e 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_RESOURCE_H
 #define __ASM_MIPS_RESOURCE_H
 /*
  * 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__
 
index 9effc1d64ef1634eba3ee593794c92a2f9eead17..40c7637892b71321824b4c50244b7b283cdae128 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _MIPS_SCATTERLIST_H
-#define _MIPS_SCATTERLIST_H
+#ifndef __ASM_MIPS_SCATTERLIST_H
+#define __ASM_MIPS_SCATTERLIST_H
 
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to */
@@ -10,4 +10,4 @@ struct scatterlist {
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
-#endif /* !(_MIPS_SCATTERLIST_H) */
+#endif /* __ASM_MIPS_SCATTERLIST_H */
index d66607215505728a3d124933a75bdf40e34730c3..0453d97daae7b4399ac1fae0ad7e194143f9b70d 100644 (file)
@@ -1,188 +1,6 @@
-/*
- * include/asm-mips/segment.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995 by Ralf Baechle
- *
- * Note that the quad functions are only being used for the 64 bit kernel and
- * therefore it isn't really important that they will be miscompiled for
- * 32-bit kernels.
- */
-#ifndef __ASM_MIPS_SEGMENT_H
-#define __ASM_MIPS_SEGMENT_H
+#ifndef __ALPHA_SEGMENT_H
+#define __ALPHA_SEGMENT_H
 
-#ifndef __LANGUAGE_ASSEMBLY__
-/*
- * For memcpy()
- */
-#include <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
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
new file mode 100644 (file)
index 0000000..6d52784
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * SMP- and interrupt-safe semaphores..
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * (C) Copyright 1996  Linus Torvalds, Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SEMAPHORE_H
+#define __ASM_MIPS_SEMAPHORE_H
+
+#include <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 */
diff --git a/include/asm-mips/sgi.h b/include/asm-mips/sgi.h
new file mode 100644 (file)
index 0000000..4e5f120
--- /dev/null
@@ -0,0 +1,42 @@
+/* $Id: sgi.h,v 1.1 1997/06/06 09:39:54 ralf Exp $
+ * sgi.h: Definitions specific to SGI machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ */
+#ifndef _MIPS_SGI_H
+#define _MIPS_SGI_H
+
+/* UP=UniProcessor MP=MultiProcessor(capable) */
+enum sgi_mach {
+       ip4,     /* R2k UP */
+       ip5,     /* R2k MP */
+       ip6,     /* R3k UP */
+       ip7,     /* R3k MP */
+       ip9,     /* R3k UP */
+       ip12,    /* R3kA UP, Indigo */
+       ip15,    /* R3kA MP */
+       ip17,    /* R4K UP */
+       ip19,    /* R4K MP */
+       ip20,    /* R4K UP, Indigo */
+       ip21,    /* TFP MP */
+       ip22,    /* R4x00 UP, Indigo2 */
+       ip25,    /* R10k MP */
+       ip26,    /* TFP UP, Indigo2 */
+       ip28,    /* R10k UP, Indigo2 */
+       ip30,
+       ip32,
+};
+
+extern enum sgi_mach sgimach;
+extern void sgi_sysinit(void);
+
+/* Many I/O space registers are byte sized and are contained within
+ * one byte per word, specifically the MSB, this macro helps out.
+ */
+#ifdef __MIPSEL__
+#define SGI_MSB(regaddr)   (regaddr)
+#else
+#define SGI_MSB(regaddr)   ((regaddr) | 0x3)
+#endif
+
+#endif /* !(_MIPS_SGI_H) */
diff --git a/include/asm-mips/sgialib.h b/include/asm-mips/sgialib.h
new file mode 100644 (file)
index 0000000..9c311be
--- /dev/null
@@ -0,0 +1,118 @@
+/* $Id: sgialib.h,v 1.1 1997/06/06 09:39:56 ralf Exp $
+ * sgialib.h: SGI ARCS firmware interface library for the Linux kernel.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIALIB_H
+#define _MIPS_SGIALIB_H
+
+#include <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) */
diff --git a/include/asm-mips/sgiarcs.h b/include/asm-mips/sgiarcs.h
new file mode 100644 (file)
index 0000000..5416ee9
--- /dev/null
@@ -0,0 +1,351 @@
+/* $Id: sgiarcs.h,v 1.1 1997/06/06 09:39:58 ralf Exp $
+ * SGI ARCS firmware interface defines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIARCS_H
+#define _MIPS_SGIARCS_H
+
+/* Various ARCS error codes. */
+#define PROM_ESUCCESS                   0x00
+#define PROM_E2BIG                      0x01
+#define PROM_EACCESS                    0x02
+#define PROM_EAGAIN                     0x03
+#define PROM_EBADF                      0x04
+#define PROM_EBUSY                      0x05
+#define PROM_EFAULT                     0x06
+#define PROM_EINVAL                     0x07
+#define PROM_EIO                        0x08
+#define PROM_EISDIR                     0x09
+#define PROM_EMFILE                     0x0a
+#define PROM_EMLINK                     0x0b
+#define PROM_ENAMETOOLONG               0x0c
+#define PROM_ENODEV                     0x0d
+#define PROM_ENOENT                     0x0e
+#define PROM_ENOEXEC                    0x0f
+#define PROM_ENOMEM                     0x10
+#define PROM_ENOSPC                     0x11
+#define PROM_ENOTDIR                    0x12
+#define PROM_ENOTTY                     0x13
+#define PROM_ENXIO                      0x14
+#define PROM_EROFS                      0x15
+/* SGI ARCS specific errno's. */
+#define PROM_EADDRNOTAVAIL              0x1f
+#define PROM_ETIMEDOUT                  0x20
+#define PROM_ECONNABORTED               0x21
+#define PROM_ENOCONNECT                 0x22
+
+/* Device classes, types, and identifiers for prom
+ * device inventory queries.
+ */
+enum linux_devclass {
+       system, processor, cache, adapter, controller, peripheral, memory
+};
+
+enum linux_devtypes {
+       /* Generic stuff. */
+       Arc, Cpu, Fpu,
+
+       /* Primary insn and data caches. */
+       picache, pdcache,
+
+       /* Secondary insn, data, and combined caches. */
+       sicache, sdcache, sccache,
+
+       memdev, eisa_adapter, tc_adapter, scsi_adapter, dti_adapter,
+       multifunc_adapter, dsk_controller, tp_controller, cdrom_controller,
+       worm_controller, serial_controller, net_controller, disp_controller,
+       parallel_controller, ptr_controller, kbd_controller, audio_controller,
+       misc_controller, disk_peripheral, flpy_peripheral, tp_peripheral,
+       modem_peripheral, monitor_peripheral, printer_peripheral,
+       ptr_peripheral, kbd_peripheral, term_peripheral, line_peripheral,
+       net_peripheral, misc_peripheral, anon
+};
+
+enum linux_identifier {
+       bogus, ronly, removable, consin, consout, input, output
+};
+
+/* A prom device tree component. */
+struct linux_component {
+       enum linux_devclass     class;   /* node class */
+       enum linux_devtypes     type;    /* node type */
+       enum linux_identifier   iflags;  /* node flags */
+       unsigned short          vers;    /* node version */
+       unsigned short          rev;     /* node revision */
+       unsigned long           key;     /* completely magic */
+       unsigned long           amask;   /* XXX affinity mask??? */
+       unsigned long           cdsize;  /* size of configuration data */
+       unsigned long           ilen;    /* length of string identifier */
+       char                   *iname;   /* string identifier */
+};
+typedef struct linux_component pcomponent;
+
+struct linux_sysid {
+       char vend[8], prod[8];
+};
+
+/* ARCS prom memory descriptors. */
+enum linux_memtypes {
+       eblock,  /* exception block */
+       rvpage,  /* ARCS romvec page */
+       fcontig, /* Contiguous and free */
+       free,    /* Generic free memory */
+       bmem,    /* Borken memory, don't use */
+       prog,    /* A loaded program resides here */
+       atmp,    /* ARCS temporary storage area, wish Sparc OpenBoot told this */
+       aperm,   /* ARCS permanent storage... */
+};
+
+struct linux_mdesc {
+       enum linux_memtypes type;
+       unsigned long base;
+       unsigned long pages;
+};
+
+/* Time of day descriptor. */
+struct linux_tinfo {
+       unsigned short yr;
+       unsigned short mnth;
+       unsigned short day;
+       unsigned short hr;
+       unsigned short min;
+       unsigned short sec;
+       unsigned short msec;
+};
+
+/* ARCS virtual dirents. */
+struct linux_vdirent {
+       unsigned long namelen;
+       unsigned char attr;
+       char fname[32]; /* XXX imperical, should be a define */
+};
+
+/* Other stuff for files. */
+enum linux_omode {
+       rdonly, wronly, rdwr, wronly_creat, rdwr_creat,
+       wronly_ssede, rdwr_ssede, dirent, dirent_creat
+};
+
+enum linux_seekmode {
+       absolute, relative
+};
+
+enum linux_mountops {
+       media_load, media_unload
+};
+
+/* This prom has a bolixed design. */
+struct linux_bigint {
+#ifdef __MIPSEL__
+       unsigned long lo;
+       long hi;
+#else /* !(__MIPSEL__) */
+       long hi;
+       unsigned long lo;
+#endif
+};
+
+struct linux_finfo {
+       struct linux_bigint   begin;
+       struct linux_bigint   end;
+       struct linux_bigint   cur;
+       enum linux_devtypes dtype;
+       unsigned long         namelen;
+       unsigned char         attr;
+       char                  name[32]; /* XXX imperical, should be define */
+};
+
+struct linux_romvec {
+       /* Load an executable image. */
+       long (*load)(char *file, unsigned long end,
+                    unsigned long *start_pc,
+                    unsigned long *end_addr);
+
+       /* Invoke a standalong image. */
+       long (*invoke)(unsigned long startpc, unsigned long sp,
+                      long argc, char **argv, char **envp);
+
+       /* Load and begin execution of a standalong image. */
+       long (*exec)(char *file, long argc, char **argv, char **envp);
+
+       void (*halt)(void);     /* Halt the machine. */
+       void (*pdown)(void);    /* Power down the machine. */
+       void (*restart)(void);  /* XXX soft reset??? */
+       void (*reboot)(void);   /* Reboot the machine. */
+       void (*imode)(void);    /* Enter PROM interactive mode. */
+       int _unused1; /* padding */
+
+       /* PROM device tree interface. */
+       pcomponent *(*next_component)(pcomponent *this);
+       pcomponent *(*child_component)(pcomponent *this);
+       pcomponent *(*parent_component)(pcomponent *this);
+       long (*component_data)(void *opaque_data, pcomponent *this);
+       pcomponent *(*child_add)(pcomponent *this,
+                                pcomponent *tmp,
+                                void *opaque_data);
+       long (*comp_del)(pcomponent *this);
+       pcomponent *(*component_by_path)(char *file);
+
+       /* Misc. stuff. */
+       long (*cfg_save)(void);
+       struct linux_sysid *(*get_sysid)(void);
+
+       /* Probing for memory. */
+       struct linux_mdesc *(*get_mdesc)(struct linux_mdesc *curr);
+       long _unused2; /* padding */
+
+       struct linux_tinfo *(*get_tinfo)(void);
+       unsigned long (*get_rtime)(void);
+
+       /* File type operations. */
+       long (*get_vdirent)(unsigned long fd, struct linux_vdirent *entry,
+                           unsigned long num, unsigned long *count);
+       long (*open)(char *file, enum linux_omode mode, unsigned long *fd);
+       long (*close)(unsigned long fd);
+       long (*read)(unsigned long fd, void *buffer, unsigned long num,
+                    unsigned long *count);
+       long (*get_rstatus)(unsigned long fd);
+       long (*write)(unsigned long fd, void *buffer, unsigned long num,
+                     unsigned long *count);
+       long (*seek)(unsigned long fd, struct linux_bigint *offset,
+                    enum linux_seekmode smode);
+       long (*mount)(char *file, enum linux_mountops op);
+
+       /* Dealing with firmware environment variables. */
+       char *(*get_evar)(char *name);
+       long (*set_evar)(char *name, char *value);
+
+       long (*get_finfo)(unsigned long fd, struct linux_finfo *buf);
+       long (*set_finfo)(unsigned long fd, unsigned long flags,
+                         unsigned long mask);
+
+       /* Miscellaneous. */
+       void (*cache_flush)(void);
+};
+
+/* The SGI ARCS parameter block is in a fixed location for standalone
+ * programs to access PROM facilities easily.
+ */
+struct linux_promblock {
+       long                 magic;       /* magic cookie */
+#define PROMBLOCK_MAGIC      0x53435241
+
+       unsigned long        len;          /* length of parm block */
+       unsigned short       ver;          /* ARCS firmware version */
+       unsigned short       rev;          /* ARCS firmware revision */
+       long                *rs_block;     /* Restart block. */
+       long                *dbg_block;    /* Debug block. */
+       long                *gevect;       /* XXX General vector??? */
+       long                *utlbvect;     /* XXX UTLB vector??? */
+       unsigned long        rveclen;      /* Size of romvec struct. */
+       struct linux_romvec *romvec;       /* Function interface. */
+       unsigned long        pveclen;      /* Length of private vector. */
+       long                *pvector;      /* Private vector. */
+       long                 adap_cnt;     /* Adapter count. */
+       long                 adap_typ0;    /* First adapter type. */
+       long                 adap_vcnt0;   /* Adapter 0 vector count. */
+       long                *adap_vector;  /* Adapter 0 vector ptr. */
+       long                 adap_typ1;    /* Second adapter type. */
+       long                 adap_vcnt1;   /* Adapter 1 vector count. */
+       long                *adap_vector1; /* Adapter 1 vector ptr. */
+       /* More adapter vectors go here... */
+};
+
+#define PROMBLOCK ((struct linux_promblock *)0xA0001000UL)
+#define ROMVECTOR ((PROMBLOCK)->romvec)
+
+/* Cache layout parameter block. */
+union linux_cache_key {
+       struct param {
+#ifdef __MIPSEL__
+               unsigned short size;
+               unsigned char lsize;
+               unsigned char bsize;
+#else /* !(__MIPSEL__) */
+               unsigned char bsize;
+               unsigned char lsize;
+               unsigned short size;
+#endif
+       } info;
+       unsigned long allinfo;
+};
+
+/* Configuration data. */
+struct linux_cdata {
+       char *name;
+       int mlen;
+       enum linux_devtypes type;
+};
+
+/* Common SGI ARCS firmware file descriptors. */
+#define SGIPROM_STDIN     0
+#define SGIPROM_STDOUT    1
+
+/* Common SGI ARCS firmware file types. */
+#define SGIPROM_ROFILE    0x01  /* read-only file */
+#define SGIPROM_HFILE     0x02  /* hidden file */
+#define SGIPROM_SFILE     0x04  /* System file */
+#define SGIPROM_AFILE     0x08  /* Archive file */
+#define SGIPROM_DFILE     0x10  /* Directory file */
+#define SGIPROM_DELFILE   0x20  /* Deleted file */
+
+/* SGI ARCS boot record information. */
+struct sgi_partition {
+       unsigned char flag;
+#define SGIPART_UNUSED 0x00
+#define SGIPART_ACTIVE 0x80
+
+       unsigned char shead, ssect, scyl; /* unused */
+       unsigned char systype; /* OS type, Irix or NT */
+       unsigned char ehead, esect, ecyl; /* unused */
+       unsigned char rsect0, rsect1, rsect2, rsect3;
+       unsigned char tsect0, tsect1, tsect2, tsect3;
+};
+
+#define SGIBBLOCK_MAGIC   0xaa55
+#define SGIBBLOCK_MAXPART 0x0004
+
+struct sgi_bootblock {
+       unsigned char _unused[446];
+       struct sgi_partition partitions[SGIBBLOCK_MAXPART];
+       unsigned short magic;
+};
+
+/* BIOS parameter block. */
+struct sgi_bparm_block {
+       unsigned short bytes_sect;    /* bytes per sector */
+       unsigned char  sect_clust;    /* sectors per cluster */
+       unsigned short sect_resv;     /* reserved sectors */
+       unsigned char  nfats;         /* # of allocation tables */
+       unsigned short nroot_dirents; /* # of root directory entries */
+       unsigned short sect_volume;   /* sectors in volume */
+       unsigned char  media_type;    /* media descriptor */
+       unsigned short sect_fat;      /* sectors per allocation table */
+       unsigned short sect_track;    /* sectors per track */
+       unsigned short nheads;        /* # of heads */
+       unsigned short nhsects;       /* # of hidden sectors */
+};
+
+struct sgi_bsector {
+       unsigned char   jmpinfo[3];
+       unsigned char   manuf_name[8];
+       struct sgi_bparm_block info;
+};
+
+/* Debugging block used with SGI symmon symbolic debugger. */
+#define SMB_DEBUG_MAGIC   0xfeeddead
+struct linux_smonblock {
+       unsigned long   magic;
+       void            (*handler)(void);  /* Breakpoint routine. */
+       unsigned long   dtable_base;       /* Base addr of dbg table. */
+       int             (*printf)(const char *fmt, ...);
+       unsigned long   btable_base;       /* Breakpoint table. */
+       unsigned long   mpflushreqs;       /* SMP cache flush request list. */
+       unsigned long   ntab;              /* Name table. */
+       unsigned long   stab;              /* Symbol table. */
+       int             smax;              /* Max # of symbols. */
+};
+
+#endif /* !(_MIPS_SGIARCS_H) */
diff --git a/include/asm-mips/sgidefs.h b/include/asm-mips/sgidefs.h
new file mode 100644 (file)
index 0000000..72d2534
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ *
+ * Definitions commonly used in SGI style code.
+ */
+#ifndef __ASM_SGIDEFS_H
+#define __ASM_SGIDEFS_H
+
+/*
+ * There are compilers out there that don't define _MIPS_ISA, _MIPS_SIM,
+ * _MIPS_SZINT, _MIPS_SZLONG, _MIPS_SZPTR.  So we notify the user about this
+ * problem.  The kernel sources are aware of this problem, so we don't warn
+ * when compiling the kernel.
+ */
+#if !defined(_MIPS_ISA) && !defined(__KERNEL__)
+#warning "Macro _MIPS_ISA has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SIM) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SIM has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZINT) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZINT has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZLONG) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZLONG has not been defined by specs file"
+#endif
+
+#if !defined(_MIPS_SZPTR) && !defined(__KERNEL__)
+#warning "Macro _MIPS_SZPTR has not been defined by specs file"
+#endif
+
+#if (!defined(_MIPS_ISA) || \
+     !defined(_MIPS_SIM) || \
+     !defined(_MIPS_SZINT) || \
+     !defined(_MIPS_SZLONG) || \
+     !defined(_MIPS_SZPTR)) && !defined(__KERNEL__)
+#warning "Please update your GCC to GCC 2.7.2-4 or newer"
+#endif
+
+/*
+ * Now lets try our best to supply some reasonable default values for
+ * whatever defines GCC didn't supply.  This cannot be done correct for
+ * all possible combinations of options, so be careful with your options
+ * to GCC.  Best bet is to keep your fingers off the a.out GCC and use
+ * ELF GCC 2.7.2-3 where possible.
+ */
+#ifndef _MIPS_ISA
+#if __mips == 1
+#define _MIPS_ISA      _MIPS_ISA_MIPS1
+/* It is impossible to handle the -mips2 case correct.  */
+#elif __mips == 3
+#define _MIPS_ISA      _MIPS_ISA_MIPS3
+#elif __mips == 4
+#define _MIPS_ISA      _MIPS_ISA_MIPS4
+#else /* __mips must be 5 */
+#define _MIPS_ISA      _MIPS_ISA_MIPS5
+#endif
+#endif
+#ifndef _MIPS_SIM
+#define _MIPS_SIM      _MIPS_SIM_ABI32
+#endif
+#ifndef _MIPS_SZINT
+#define _MIPS_SZINT    32
+#endif
+#ifndef _MIPS_SZLONG
+#define _MIPS_SZLONG   32
+#endif
+#ifndef _MIPS_SZPTR
+#define _MIPS_SZPTR    32
+#endif
+
+/*
+ * Definitions for the ISA level
+ */
+#define _MIPS_ISA_MIPS1 1
+#define _MIPS_ISA_MIPS2 2
+#define _MIPS_ISA_MIPS3 3
+#define _MIPS_ISA_MIPS4 4
+#define _MIPS_ISA_MIPS5 5
+
+/*
+ * Subprogram calling convention
+ *
+ * At the moment only _MIPS_SIM_ABI32 is in use.  This will change rsn.
+ * Until GCC 2.8.0 is released don't rely on this definitions because the
+ * 64bit code is essentially using the 32bit interface model just with
+ * 64bit registers.
+ */
+#define _MIPS_SIM_ABI32                1
+#define _MIPS_SIM_NABI32       2
+#define _MIPS_SIM_ABI64                3
+
+#endif /* __ASM_SGIDEFS_H */
diff --git a/include/asm-mips/sgihpc.h b/include/asm-mips/sgihpc.h
new file mode 100644 (file)
index 0000000..9ae98ac
--- /dev/null
@@ -0,0 +1,340 @@
+/* $Id: sgihpc.h,v 1.1 1997/06/06 09:40:02 ralf Exp $
+ * sgihpc.h: Various HPC I/O controller defines.  The HPC is basically
+ *           the approximate functional equivalent of the Sun SYSIO
+ *           on SGI INDY machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_SGIHPC_H
+#define _MIPS_SGIHPC_H
+
+#include <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) */
diff --git a/include/asm-mips/sgimc.h b/include/asm-mips/sgimc.h
new file mode 100644 (file)
index 0000000..d2e96b9
--- /dev/null
@@ -0,0 +1,223 @@
+/* $Id: sgimc.h,v 1.1 1997/06/06 09:40:04 ralf Exp $
+ * sgimc.h: Definitions for memory controller hardware found on
+ *          SGI IP20, IP22, IP26, and IP28 machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _MIPS_SGIMC_H
+#define _MIPS_SGIMC_H
+
+struct sgimc_misc_ctrl {
+       unsigned long _unused1;
+       volatile unsigned long cpuctrl0;     /* CPU control register 0, readwrite */
+#define SGIMC_CCTRL0_REFS         0x0000000f /* REFS mask */
+#define SGIMC_CCTRL0_EREFRESH     0x00000010 /* Memory refresh enable */
+#define SGIMC_CCTRL0_EPERRGIO     0x00000020 /* GIO parity error enable */
+#define SGIMC_CCTRL0_EPERRMEM     0x00000040 /* Main mem parity error enable */
+#define SGIMC_CCTRL0_EPERRCPU     0x00000080 /* CPU bus parity error enable */
+#define SGIMC_CCTRL0_WDOG         0x00000100 /* Watchdog timer enable */
+#define SGIMC_CCTRL0_SYSINIT      0x00000200 /* System init bit */
+#define SGIMC_CCTRL0_GFXRESET     0x00000400 /* Graphics interface reset */
+#define SGIMC_CCTRL0_EISALOCK     0x00000800 /* Lock CPU from memory for EISA */
+#define SGIMC_CCTRL0_EPERRSCMD    0x00001000 /* SysCMD bus parity error enable */
+#define SGIMC_CCTRL0_IENAB        0x00002000 /* Allow interrupts from MC */
+#define SGIMC_CCTRL0_ESNOOP       0x00004000 /* Snooping I/O enable */
+#define SGIMC_CCTRL0_EPROMWR      0x00008000 /* Prom writes from cpu enable */
+#define SGIMC_CCTRL0_WRESETPMEM   0x00010000 /* Perform warm reset, preserves mem */
+#define SGIMC_CCTRL0_LENDIAN      0x00020000 /* Put MC in little-endian mode */
+#define SGIMC_CCTRL0_WRESETDMEM   0x00040000 /* Warm reset, destroys mem contents */
+#define SGIMC_CCTRL0_CMEMBADPAR   0x02000000 /* Generate bad perr from cpu to mem */
+#define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */
+#define SGIMC_CCTRL0_GIOBTOB      0x08000000 /* Allow GIO back to back writes */
+
+       unsigned long _unused2;
+       volatile unsigned long cpuctrl1;     /* CPU control register 1, readwrite */
+#define SGIMC_CCTRL1_EGIOTIMEO    0x00000010 /* GIO bus timeout enable */
+#define SGIMC_CCTRL1_FIXEDEHPC    0x00001000 /* Fixed HPC endianness */
+#define SGIMC_CCTRL1_LITTLEHPC    0x00002000 /* Little endian HPC */
+#define SGIMC_CCTRL1_FIXEDEEXP0   0x00004000 /* Fixed EXP0 endianness */
+#define SGIMC_CCTRL1_LITTLEEXP0   0x00008000 /* Little endian EXP0 */
+#define SGIMC_CCTRL1_FIXEDEEXP1   0x00010000 /* Fixed EXP1 endianness */
+#define SGIMC_CCTRL1_LITTLEEXP1   0x00020000 /* Little endian EXP1 */
+
+       unsigned long _unused3;
+       volatile unsigned long watchdogt;    /* Watchdog reg rdonly, write clears */
+
+       unsigned long _unused4;
+       volatile unsigned long systemid;     /* MC system ID register, readonly */
+#define SGIMC_SYSID_MASKREV       0x0000000f /* Revision of MC controller */
+#define SGIMC_SYSID_EPRESENT      0x00000010 /* Indicates presence of EISA bus */
+
+       unsigned long _unused5[3];
+       volatile unsigned long divider;      /* Divider reg for RPSS */
+
+       unsigned long _unused6;
+       volatile unsigned char eeprom;       /* EEPROM byte reg for r4k */
+#define SGIMC_EEPROM_PRE          0x00000001 /* eeprom chip PRE pin assertion */
+#define SGIMC_EEPROM_CSEL         0x00000002 /* Active high, eeprom chip select */
+#define SGIMC_EEPROM_SECLOCK      0x00000004 /* EEPROM serial clock */
+#define SGIMC_EEPROM_SDATAO       0x00000008 /* Serial EEPROM data-out */
+#define SGIMC_EEPROM_SDATAI       0x00000010 /* Serial EEPROM data-in */
+
+       unsigned char _unused7[3];
+       unsigned long _unused8[3];
+       volatile unsigned short rcntpre;     /* Preload refresh counter */
+
+       unsigned short _unused9;
+       unsigned long _unused9a;
+       volatile unsigned short rcounter;    /* Readonly refresh counter */
+
+       unsigned short _unused10;
+       unsigned long _unused11[13];
+       volatile unsigned long gioparm;      /* Parameter word for GIO64 */
+#define SGIMC_GIOPARM_HPC64       0x00000001 /* HPC talks to GIO using 64-bits */
+#define SGIMC_GIOPARM_GFX64       0x00000002 /* GFX talks to GIO using 64-bits */
+#define SGIMC_GIOPARM_EXP064      0x00000004 /* EXP(slot0) talks using 64-bits */
+#define SGIMC_GIOPARM_EXP164      0x00000008 /* EXP(slot1) talks using 64-bits */
+#define SGIMC_GIOPARM_EISA64      0x00000010 /* EISA bus talks 64-bits to GIO */
+#define SGIMC_GIOPARM_HPC264      0x00000020 /* 2nd HPX talks 64-bits to GIO */
+#define SGIMC_GIOPARM_RTIMEGFX    0x00000040 /* GFX device has realtime attr */
+#define SGIMC_GIOPARM_RTIMEEXP0   0x00000080 /* EXP(slot0) has realtime attr */
+#define SGIMC_GIOPARM_RTIMEEXP1   0x00000100 /* EXP(slot1) has realtime attr */
+#define SGIMC_GIOPARM_MASTEREISA  0x00000200 /* EISA bus can act as bus master */
+#define SGIMC_GIOPARM_ONEBUS      0x00000400 /* Exists one GIO64 pipelined bus */
+#define SGIMC_GIOPARM_MASTERGFX   0x00000800 /* GFX can act as a bus master */
+#define SGIMC_GIOPARM_MASTEREXP0  0x00001000 /* EXP(slot0) can bus master */
+#define SGIMC_GIOPARM_MASTEREXP1  0x00002000 /* EXP(slot1) can bus master */
+#define SGIMC_GIOPARM_PLINEEXP0   0x00004000 /* EXP(slot0) has pipeline attr */
+#define SGIMC_GIOPARM_PLINEEXP1   0x00008000 /* EXP(slot1) has pipeline attr */
+
+       unsigned long _unused13;
+       volatile unsigned short cputp;       /* CPU bus arb time period */
+
+       unsigned short _unused14;
+       unsigned long _unused15[3];
+       volatile unsigned short lbursttp;    /* Time period for long bursts */
+
+       unsigned short _unused16;
+       unsigned long _unused17[9];
+       volatile unsigned long mconfig0;     /* Memory config register zero */
+       unsigned long _unused18;
+       volatile unsigned long mconfig1;     /* Memory config register one */
+
+        /* These defines apply to both mconfig registers above. */
+#define SGIMC_MCONFIG_FOURMB     0x00000000  /* Physical ram = 4megs */
+#define SGIMC_MCONFIG_EIGHTMB    0x00000100  /* Physical ram = 8megs */
+#define SGIMC_MCONFIG_SXTEENMB   0x00000300  /* Physical ram = 16megs */
+#define SGIMC_MCONFIG_TTWOMB     0x00000700  /* Physical ram = 32megs */
+#define SGIMC_MCONFIG_SFOURMB    0x00000f00  /* Physical ram = 64megs */
+#define SGIMC_MCONFIG_OTEIGHTMB  0x00001f00  /* Physical ram = 128megs */
+#define SGIMC_MCONFIG_RMASK      0x00001f00  /* Ram config bitmask */
+
+       unsigned long _unused19;
+       volatile unsigned long cmacc;        /* Mem access config for CPU */
+       unsigned long _unused20;
+       volatile unsigned long gmacc;        /* Mem access config for GIO */
+
+       /* This define applies to both cmacc and gmacc registers above. */
+#define SGIMC_MACC_ALIASBIG       0x20000000 /* 512MB home for alias */
+
+       /* Error address/status regs from GIO and CPU perspectives. */
+       unsigned long _unused21;
+       volatile unsigned long cerr;         /* Error address reg for CPU */
+       unsigned long _unused22;
+       volatile unsigned long cstat;        /* Status reg for CPU */
+       unsigned long _unused23;
+       volatile unsigned long gerr;         /* Error address reg for GIO */
+       unsigned long _unused24;
+       volatile unsigned long gstat;        /* Status reg for GIO */
+
+       /* Special hard bus locking registers. */
+       unsigned long _unused25;
+       volatile unsigned char syssembit;    /* Uni-bit system semaphore */
+       unsigned char _unused26[3];
+       unsigned long _unused27;
+       volatile unsigned char mlock;        /* Global GIO memory access lock */
+       unsigned char _unused28[3];
+       unsigned long _unused29;
+       volatile unsigned char elock;        /* Locks EISA from GIO accesses */
+
+       /* GIO dma control registers. */
+       unsigned char _unused30[3];
+       unsigned long _unused31[14];
+       volatile unsigned long gio_dma_trans;/* DMA mask to translation GIO addrs */
+       unsigned long _unused32;
+       volatile unsigned long gio_dma_sbits;/* DMA GIO addr substitution bits */
+       unsigned long _unused33;
+       volatile unsigned long dma_intr_cause; /* DMA IRQ cause indicator bits */
+       unsigned long _unused34;
+       volatile unsigned long dma_ctrl;     /* Main DMA control reg */
+
+       /* DMA TLB entry 0 */
+       unsigned long _unused35;
+       volatile unsigned long dtlb_hi0;
+       unsigned long _unused36;
+       volatile unsigned long dtlb_lo0;
+
+       /* DMA TLB entry 1 */
+       unsigned long _unused37;
+       volatile unsigned long dtlb_hi1;
+       unsigned long _unused38;
+       volatile unsigned long dtlb_lo1;
+
+       /* DMA TLB entry 2 */
+       unsigned long _unused39;
+       volatile unsigned long dtlb_hi2;
+       unsigned long _unused40;
+       volatile unsigned long dtlb_lo2;
+
+       /* DMA TLB entry 3 */
+       unsigned long _unused41;
+       volatile unsigned long dtlb_hi3;
+       unsigned long _unused42;
+       volatile unsigned long dtlb_lo3;
+};
+
+/* MC misc control registers live at physical 0x1fa00000. */
+extern struct sgimc_misc_ctrl *mcmisc_regs;
+extern unsigned long *rpsscounter;          /* Chirps at 100ns */
+
+struct sgimc_dma_ctrl {
+       unsigned long _unused1;
+       volatile unsigned long maddronly;   /* Address DMA goes at */
+       unsigned long _unused2;
+       volatile unsigned long maddrpdeflts; /* Same as above, plus set defaults */
+       unsigned long _unused3;
+       volatile unsigned long dmasz;       /* DMA count */
+       unsigned long _unused4;
+       volatile unsigned long ssize;       /* DMA stride size */
+       unsigned long _unused5;
+       volatile unsigned long gmaddronly;  /* Set GIO DMA but do not start trans */
+       unsigned long _unused6;
+       volatile unsigned long dmaddnpgo;   /* Set GIO DMA addr + start transfer */
+       unsigned long _unused7;
+       volatile unsigned long dmamode;     /* DMA mode config bit settings */
+       unsigned long _unused8;
+       volatile unsigned long dmacount;    /* Zoom and byte count for DMA */
+       unsigned long _unused9;
+       volatile unsigned long dmastart;    /* Pedal to the metal. */
+       unsigned long _unused10;
+       volatile unsigned long dmarunning;  /* DMA op is in progress */
+       unsigned long _unused11;
+
+       /* Set dma addr, defaults, and kick it */
+       volatile unsigned long maddr_defl_go; /* go go go! -lm */
+};
+
+/* MC controller dma regs live at physical 0x1fa02000. */
+extern struct sgimc_dma_ctrl *dmactrlregs;
+
+/* Base location of the two ram banks found in IP2[0268] machines. */
+#define SGIMC_SEG0_BADDR     0x08000000
+#define SGIMC_SEG1_BADDR     0x20000000
+
+/* Maximum size of the above banks are per machine. */
+extern unsigned long sgimc_seg0_size, sgimc_seg1_size;
+#define SGIMC_SEG0_SIZE_ALL         0x10000000 /* 256MB */
+#define SGIMC_SEG1_SIZE_IP20_IP22   0x08000000 /* 128MB */
+#define SGIMC_SEG1_SIZE_IP26_IP28   0x20000000 /* 512MB */
+
+extern void sgimc_init(void);
+
+#endif /* !(_MIPS_SGIMC_H) */
diff --git a/include/asm-mips/sgint23.h b/include/asm-mips/sgint23.h
new file mode 100644 (file)
index 0000000..a367e7b
--- /dev/null
@@ -0,0 +1,179 @@
+/* $Id: sgint23.h,v 1.1 1997/06/06 09:40:06 ralf Exp $
+ * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_SGINT23_H
+#define _MIPS_SGINT23_H
+
+/* These are the virtual IRQ numbers, we divide all IRQ's into
+ * 'spaces', the 'space' determines where and how to enable/disable
+ * that particular IRQ on an SGI machine.  Add new 'spaces' as new
+ * IRQ hardware is supported.
+ */
+#define SGINT_LOCAL0   0   /* INDY has 8 local0 irq levels */
+#define SGINT_LOCAL1   8   /* INDY has 8 local1 irq levels */
+#define SGINT_LOCAL2   16  /* INDY has 8 local2 vectored irq levels */
+#define SGINT_LOCAL3   24  /* INDY has 8 local3 vectored irq levels */
+#define SGINT_GIO      32  /* INDY has 9 GIO irq levels */
+#define SGINT_HPCDMA   41  /* INDY has 11 HPCDMA irq _sources_ */
+#define SGINT_END      52  /* End of 'spaces' */
+
+/* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */
+#define SGI_INT2_BASE 0x1fb80100 /* physical */
+#define SGI_INT3_BASE 0x1fbd9880 /* physical */
+
+struct sgi_ioc_ints {
+#ifdef __MIPSEB__
+       unsigned char _unused0[3];
+       volatile unsigned char istat0;    /* Interrupt status zero */
+#else
+       volatile unsigned char istat0;    /* Interrupt status zero */
+       unsigned char _unused0[3];
+#endif
+#define ISTAT0_FFULL           0x01
+#define ISTAT0_SCSI0           0x02
+#define ISTAT0_SCSI1           0x04
+#define ISTAT0_ENET            0x08
+#define ISTAT0_GFXDMA          0x10
+#define ISTAT0_LPR             0x20
+#define ISTAT0_HPC2            0x40
+#define ISTAT0_LIO2            0x80
+
+#ifdef __MIPSEB__
+       unsigned char _unused1[3];
+       volatile unsigned char imask0;    /* Interrupt mask zero */
+       unsigned char _unused2[3];
+       volatile unsigned char istat1;    /* Interrupt status one */
+#else
+       volatile unsigned char imask0;    /* Interrupt mask zero */
+       unsigned char _unused1[3];
+       volatile unsigned char istat1;    /* Interrupt status one */
+       unsigned char _unused2[3];
+#endif
+#define ISTAT1_ISDNI           0x01
+#define ISTAT1_PWR             0x02
+#define ISTAT1_ISDNH           0x04
+#define ISTAT1_LIO3            0x08
+#define ISTAT1_HPC3            0x10
+#define ISTAT1_AFAIL           0x20
+#define ISTAT1_VIDEO           0x40
+#define ISTAT1_GIO2            0x80
+
+#ifdef __MIPSEB__
+       unsigned char _unused3[3];
+       volatile unsigned char imask1;    /* Interrupt mask one */
+       unsigned char _unused4[3];
+       volatile unsigned char vmeistat;  /* VME interrupt status */
+       unsigned char _unused5[3];
+       volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+       unsigned char _unused6[3];
+       volatile unsigned char cmeimask1; /* VME interrupt mask one */
+       unsigned char _unused7[3];
+       volatile unsigned char cmepol;    /* VME polarity */
+#else
+       volatile unsigned char imask1;    /* Interrupt mask one */
+       unsigned char _unused3[3];
+       volatile unsigned char vmeistat;  /* VME interrupt status */
+       unsigned char _unused4[3];
+       volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+       unsigned char _unused5[3];
+       volatile unsigned char cmeimask1; /* VME interrupt mask one */
+       unsigned char _unused6[3];
+       volatile unsigned char cmepol;    /* VME polarity */
+       unsigned char _unused7[3];
+#endif
+};
+
+struct sgi_ioc_timers {
+#ifdef __MIPSEB__
+       unsigned char _unused0[3];
+       volatile unsigned char tcnt0;  /* counter 0 */
+       unsigned char _unused1[3];
+       volatile unsigned char tcnt1;  /* counter 1 */
+       unsigned char _unused2[3];
+       volatile unsigned char tcnt2;  /* counter 2 */
+       unsigned char _unused3[3];
+       volatile unsigned char tcword; /* control word */
+#else
+       volatile unsigned char tcnt0;  /* counter 0 */
+       unsigned char _unused0[3];
+       volatile unsigned char tcnt1;  /* counter 1 */
+       unsigned char _unused1[3];
+       volatile unsigned char tcnt2;  /* counter 2 */
+       unsigned char _unused2[3];
+       volatile unsigned char tcword; /* control word */
+       unsigned char _unused3[3];
+#endif
+};
+
+/* Timer control word bits. */
+#define SGINT_TCWORD_BCD    0x01 /* Use BCD mode for counters */
+#define SGINT_TCWORD_MMASK  0x0e /* Mode bitmask. */
+#define SGINT_TCWORD_MITC   0x00 /* IRQ on terminal count (doesn't work) */
+#define SGINT_TCWORD_MOS    0x02 /* One-shot IRQ mode. */
+#define SGINT_TCWORD_MRGEN  0x04 /* Normal rate generation */
+#define SGINT_TCWORD_MSWGEN 0x06 /* Square wave generator mode */
+#define SGINT_TCWORD_MSWST  0x08 /* Software strobe */
+#define SGINT_TCWORD_MHWST  0x0a /* Hardware strobe */
+#define SGINT_TCWORD_CMASK  0x30 /* Command mask */
+#define SGINT_TCWORD_CLAT   0x00 /* Latch command */
+#define SGINT_TCWORD_CLSB   0x10 /* LSB read/write */
+#define SGINT_TCWORD_CMSB   0x20 /* MSB read/write */
+#define SGINT_TCWORD_CALL   0x30 /* Full counter read/write */
+#define SGINT_TCWORD_CNT0   0x00 /* Select counter zero */
+#define SGINT_TCWORD_CNT1   0x40 /* Select counter one */
+#define SGINT_TCWORD_CNT2   0x80 /* Select counter two */
+#define SGINT_TCWORD_CRBCK  0xc0 /* Readback command */
+
+#define SGINT_TCSAMP_COUNTER  0x164
+
+struct sgi_int2_regs {
+       struct sgi_ioc_ints ints;
+
+       volatile unsigned long ledbits;   /* LED control bits */
+#define INT2_LED_TXCLK         0x01       /* GPI to TXCLK enable */
+#define INT2_LED_SERSLCT0      0x02       /* serial port0: 0=apple 1=pc */
+#define INT2_LED_SERSLCT1      0x04       /* serial port1: 0=apple 1=pc */
+#define INT2_LED_CHEAPER       0x08       /* 0=cheapernet 1=ethernet */
+#define INT2_LED_POWEROFF      0x10       /* Power-off request, active high */
+
+#ifdef __MIPSEB__
+       unsigned char _unused0[3];
+       volatile unsigned char tclear;    /* Timer clear strobe address */
+#else
+       volatile unsigned char tclear;    /* Timer clear strobe address */
+       unsigned char _unused0[3];
+#endif
+#define INT2_TCLEAR_T0CLR      0x1        /* Clear timer0 IRQ */
+#define INT2_TCLEAR_T1CLR      0x2        /* Clear timer1 IRQ */
+
+       unsigned long _unused[3];
+       struct sgi_ioc_timers timers;
+};
+
+struct sgi_int3_regs {
+       struct sgi_ioc_ints ints;
+
+#ifdef __MIPSEB__
+       unsigned char _unused0[3];
+       volatile unsigned char tclear;    /* Timer clear strobe address */
+#else
+       volatile unsigned char tclear;    /* Timer clear strobe address */
+       unsigned char _unused0[3];
+#endif
+       volatile unsigned long estatus;   /* Error status reg */
+       unsigned long _unused1[2];
+       struct sgi_ioc_timers timers;
+};
+
+extern struct sgi_int2_regs *sgi_i2regs;
+extern struct sgi_int3_regs *sgi_i3regs;
+extern struct sgi_ioc_ints *ioc_icontrol;
+extern struct sgi_ioc_timers *ioc_timers;
+extern volatile unsigned char *ioc_tclear;
+
+extern void sgint_init(void);
+extern void indy_timer_init(void);
+
+#endif /* !(_MIPS_SGINT23_H) */
index 9c5a38a40039464629fa8f369b7f7ff66140de06..b2441c81a69680b773d4714c404fd4232ce36af5 100644 (file)
@@ -39,7 +39,7 @@
 #define SHMALL                         /* max shm system wide (pages) */ \
        (1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
 /*
- * This constant is very large but the ABI in its wisdom says ...
+ * This constant is very large but the ABI in it's wisdom says ...
  */
 #define        SHMLBA 0x40000                  /* attach addr a multiple of this */
 #define SHMSEG SHMMNI                  /* max shared segs per process */
index 083a508542376c18c23f77f406aa45bd4a0a3bb2..3e7346dee1020db36ffc52323139a52a0b8fe21f 100644 (file)
@@ -1,21 +1,50 @@
 #ifndef __ASM_MIPS_SIGCONTEXT_H
 #define __ASM_MIPS_SIGCONTEXT_H
 
+#ifdef __LANGUAGE_ASSEMBLY__
+
+#define SC_REGMASK     0
+#define SC_STATUS      4
+#define SC_PC          8
+#define SC_REGS                16
+#define SC_FPREGS      272
+#define SC_OWNEDFP     528
+#define SC_FPC_CSR     532
+#define SC_FPC_EIR     536
+#define SC_SSFLAGS     540
+#define SC_MDHI                544
+#define SC_MDLO                552
+
+#endif
+
+#if defined(__LANGUAGE_C__) || \
+    defined(_LANGUAGE_C) || \
+    defined(__LANGUAGE_C_PLUS_PLUS__) || \
+    defined(__LANGUAGE_OBJECTIVE_C__)
+
 /*
- * This struct isn't in the ABI, so we continue to use the old
- * pre 1.3 definition.  Needs to be changed for 64 bit kernels,
- * but it's 4am ...
+ * Whenever this structure is changed you must update the offsets in
+ * arch/mips/mips<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 */
index 313e36c48c3b8c6102cefd54ba136e5caf62c481..d21105928470be807cf8b4cce8d28019082ef4a8 100644 (file)
@@ -1,26 +1,41 @@
-#ifndef __ASM_MIPS_SIGNAL_H
-#define __ASM_MIPS_SIGNAL_H
-
 /*
- * For now ...
+ * Linux/MIPS specific definitions for signals.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
  */
-#include <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.
  */
@@ -58,7 +73,10 @@ typedef struct {
 #define SIGPROF                29      /* Profiling alarm clock (4.2 BSD).  */
 #define SIGXCPU                30      /* CPU limit exceeded (4.2 BSD).  */
 #define SIGXFSZ                31      /* File size limit exceeded (4.2 BSD).  */
+#endif /* need signums */
+#undef __need_signums
 
+#ifdef __ASM_MIPS_SIGNAL_H
 /*
  * sa_flags values: SA_STACK is not currently supported, but will allow the
  * usage of signal stacks by using the (now obsolete) sa_restorer field in
@@ -87,37 +105,46 @@ typedef struct {
  */
 #define SA_PROBE SA_ONESHOT
 #define SA_SAMPLE_RANDOM SA_RESTART
-#endif
+#endif /* __KERNEL__ */
 
-#define SIG_BLOCK          1   /* for blocking signals */
-#define SIG_UNBLOCK        2   /* for unblocking signals */
-#define SIG_SETMASK        3   /* for setting the signal mask */
+#define SIG_BLOCK      1       /* for blocking signals */
+#define SIG_UNBLOCK    2       /* for unblocking signals */
+#define SIG_SETMASK    3       /* for setting the signal mask */
+#define SIG_SETMASK32  256     /* Goodie from SGI for BSD compatibility:
+                                  set only the low 32 bit of the sigset.  */
 
+#ifndef __sighandler_t_defined
+#define __sighandler_t_defined
 /* Type of a signal handler.  */
 typedef void (*__sighandler_t)(int);
+#endif
+#endif
 
+#if !defined (__fake_sigfuns_defined) && \
+    (defined (__ASM_MIPS_SIGNAL_H) || defined (__need_fake_sigfuns))
+#define __fake_sigfuns_defined
 /* Fake signal functions */
 #define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
 #define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
 #define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+#endif
+#undef __need_fake_sigfuns
 
+#ifdef __ASM_MIPS_SIGNAL_H
 struct sigaction {
        unsigned int    sa_flags;
        __sighandler_t  sa_handler;
        sigset_t        sa_mask;
-       /*
-        * To keep the ABI structure size we have to fill a little gap ...
-        */
-       unsigned int    sa_mask_pad[2];
+       unsigned int    __pad0[3];      /* reserved, keep size constant */
 
        /* Abi says here follows reserved int[2] */
        void            (*sa_restorer)(void);
-#if __mips < 3
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
        /*
         * For 32 bit code we have to pad struct sigaction to get
         * constant size for the ABI
         */
-       int             pad0[1];        /* reserved */
+       int             __pad1[1];      /* reserved */
 #endif
 };
 
@@ -125,4 +152,27 @@ struct sigaction {
 #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) */
diff --git a/include/asm-mips/slots.h b/include/asm-mips/slots.h
deleted file mode 100644 (file)
index 4b9eb35..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-mips/slots.h
- *
- * Copyright (C) 1994 by Waldorf Electronics
- * Written by Ralf Baechle
- */
-#ifndef __ASM_MIPS_SLOTS_H
-#define __ASM_MIPS_SLOTS_H
-
-/*
- * SLOTSPACE is the address to which the physical address 0
- * of the Slotspace is mapped by the chipset in the main CPU's
- * address space.
- */
-#define SLOTSPACE 0xe1000000
-
-#endif /* __ASM_MIPS_SLOTS_H */
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
new file mode 100644 (file)
index 0000000..780beff
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_SMP_H
+#define __ASM_MIPS_SMP_H
+
+/* We'll get here eventually.. */
+
+#endif /* __ASM_MIPS_SMP_H */
diff --git a/include/asm-mips/smp_lock.h b/include/asm-mips/smp_lock.h
new file mode 100644 (file)
index 0000000..c9482ab
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996  Ralf Baechle
+ *
+ * Linux/MIPS SMP support.  Just a dummy to make building possible.
+ */
+#ifndef __ASM_MIPS_SMPLOCK_H
+#define __ASM_MIPS_SMPLOCK_H
+
+#ifndef __SMP__
+
+#define lock_kernel()          do { } while(0)
+#define unlock_kernel()                do { } while(0)
+#define release_kernel_lock(task, cpu, depth)  ((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
+
+#else
+
+#error "We do not support SMP on MIPS yet"
+
+#endif /* __SMP__ */
+
+#endif /* __ASM_MIPS_SMPLOCK_H */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
new file mode 100644 (file)
index 0000000..9ed5919
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SNI specific definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SNI_H 
+#define __ASM_MIPS_SNI_H 
+
+#define SNI_PORT_BASE  0xb4000000
+
+/*
+ * ASIC PCI registers for little endian configuration.
+ */
+#ifndef __MIPSEL__
+#error "Fix me for big endian"
+#endif
+#define PCIMT_UCONF            0xbfff0000
+#define PCIMT_IOADTIMEOUT2     0xbfff0008
+#define PCIMT_IOMEMCONF                0xbfff0010
+#define PCIMT_IOMMU            0xbfff0018
+#define PCIMT_IOADTIMEOUT1     0xbfff0020
+#define PCIMT_DMAACCESS                0xbfff0028
+#define PCIMT_DMAHIT           0xbfff0030
+#define PCIMT_ERRSTATUS                0xbfff0038
+#define PCIMT_ERRADDR          0xbfff0040
+#define PCIMT_SYNDROME         0xbfff0048
+#define PCIMT_ITPEND           0xbfff0050
+#define PCIMT_IRQSEL           0xbfff0058
+#define PCIMT_TESTMEM          0xbfff0060
+#define PCIMT_ECCREG           0xbfff0068
+#define PCIMT_CONFIG_ADDRESS   0xbfff0070
+#define PCIMT_ASIC_ID          0xbfff0078      /* read */
+#define PCIMT_SOFT_RESET       0xbfff0078      /* write */
+#define PCIMT_PIA_OE           0xbfff0080
+#define PCIMT_PIA_DATAOUT      0xbfff0088
+#define PCIMT_PIA_DATAIN       0xbfff0090
+#define PCIMT_CACHECONF                0xbfff0098
+#define PCIMT_INVSPACE         0xbfff00a0
+#define PCIMT_PCI_CONF         0xbfff0100
+
+/*
+ * Data port for the PCI bus.
+ */
+#define PCIMT_CONFIG_DATA      0xb4000cfc
+
+/*
+ * Board specific registers
+ */
+#define PCIMT_CSMSR            0xbfd00000
+#define PCIMT_CSSWITCH         0xbfd10000
+#define PCIMT_CSITPEND         0xbfd20000
+#define PCIMT_AUTO_PO_EN       0xbfd30000
+#define PCIMT_CLR_TEMP         0xbfd40000
+#define PCIMT_AUTO_PO_DIS      0xbfd50000
+#define PCIMT_EXMSR            0xbfd60000
+#define PCIMT_UNUSED1          0xbfd70000
+#define PCIMT_CSWCSM           0xbfd80000
+#define PCIMT_UNUSED2          0xbfd90000
+#define PCIMT_CSLED            0xbfda0000
+#define PCIMT_CSMAPISA         0xbfdb0000
+#define PCIMT_CSRSTBP          0xbfdc0000
+#define PCIMT_CLRPOFF          0xbfdd0000
+#define PCIMT_CSTIMER          0xbfde0000
+#define PCIMT_PWDN             0xbfdf0000
+
+/*
+ * Interrupt 0-16 are reserved for PCI and EISA interrupts.  The
+ * interrupts from 16 are assigned to the other interrupts generated
+ * by the PCI chipset.
+ */
+#define PCIMT_IRQ_ETHERNET     16
+#define PCIMT_IRQ_TEMPERATURE  17
+#define PCIMT_IRQ_EISA_NMI     18
+#define PCIMT_IRQ_POWER_OFF    19
+#define PCIMT_IRQ_BUTTON       20
+#define PCIMT_IRQ_INTA         21
+#define PCIMT_IRQ_INTB         22
+#define PCIMT_IRQ_INTC         23
+#define PCIMT_IRQ_INTD         24
+#define PCIMT_IRQ_SCSI         25
+
+/*
+ * Base address for the mapped 16mb EISA bus segment.
+ */
+#define PCIMT_EISA_BASE                0xb0000000
+
+#endif /* __ASM_MIPS_SNI_H */
index ff829a8649c68725c43e09e692eb9a1ae408b39c..b00108aaea19f39cdc982764271a28b39aeda35c 100644 (file)
@@ -2,17 +2,7 @@
 #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 */
diff --git a/include/asm-mips/sockios.h b/include/asm-mips/sockios.h
new file mode 100644 (file)
index 0000000..18ca5f9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Socket-level I/O control calls.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SOCKIOS_H
+#define __ASM_MIPS_SOCKIOS_H
+
+#include <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 */
diff --git a/include/asm-mips/softirq.h b/include/asm-mips/softirq.h
new file mode 100644 (file)
index 0000000..8d73fed
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __ASM_MIPS_SOFTIRQ_H
+#define __ASM_MIPS_SOFTIRQ_H
+
+/* The locking mechanism for base handlers, to prevent re-entrancy,
+ * is entirely private to an implementation, it should not be
+ * referenced at all outside of this file.
+ */
+extern atomic_t __mips_bh_counter;
+
+#define get_active_bhs()       (bh_mask & bh_active)
+
+static inline void clear_active_bhs(unsigned long x)
+{
+       unsigned long temp;
+
+       __asm__ __volatile__(
+               "1:\tll\t%0,%1\n\t"
+               "and\t%0,%2\n\t"
+               "sc\t%0,%1\n\t"
+               "beqz\t%0,1b"
+               :"=&r" (temp),
+                "=m" (bh_active)
+               :"Ir" (x),
+                "m" (bh_active));
+}
+
+extern inline void init_bh(int nr, void (*routine)(void))
+{
+       bh_base[nr] = routine;
+       bh_mask_count[nr] = 0;
+       bh_mask |= 1 << nr;
+}
+
+extern inline void remove_bh(int nr)
+{
+       bh_base[nr] = NULL;
+       bh_mask &= ~(1 << nr);
+}
+
+extern inline void mark_bh(int nr)
+{
+       set_bit(nr, &bh_active);
+}
+
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void disable_bh(int nr)
+{
+       bh_mask &= ~(1 << nr);
+       bh_mask_count[nr]++;
+}
+
+extern inline void enable_bh(int nr)
+{
+       if (!--bh_mask_count[nr])
+               bh_mask |= 1 << nr;
+}
+
+/*
+ * start_bh_atomic/end_bh_atomic also nest
+ * naturally by using a counter
+ */
+extern inline void start_bh_atomic(void)
+{
+#ifdef __SMP__
+       atomic_inc(&__mips_bh_counter);
+       synchronize_irq();
+#else
+       atomic_inc(&__mips_bh_counter);
+#endif
+}
+
+extern inline void end_bh_atomic(void)
+{
+       atomic_dec(&__mips_bh_counter);
+}
+
+#ifndef __SMP__
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock()      (atomic_read(&__mips_bh_counter) ? \
+                               0 : \
+                               ((atomic_set(&__mips_bh_counter,1)),1))
+#define softirq_endlock()      (atomic_set(&__mips_bh_counter, 0))
+
+#else
+
+#error FIXME
+
+#endif /* __SMP__ */
+#endif /* __ASM_MIPS_SOFTIRQ_H */
diff --git a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h
new file mode 100644 (file)
index 0000000..85376ed
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __ASM_MIPS_SPINLOCK_H
+#define __ASM_MIPS_SPINLOCK_H
+
+#ifndef __SMP__
+
+/* gcc 2.7.2 can crash initializing an empty structure.  For now we
+   try to do though ...  */
+typedef struct { } spinlock_t;
+#define SPIN_LOCK_UNLOCKED { }
+
+#define spin_lock_init(lock)   do { } while(0)
+#define spin_lock(lock)                do { } while(0)
+#define spin_trylock(lock)     do { } while(0)
+#define spin_unlock_wait(lock) do { } while(0)
+#define spin_unlock(lock)      do { } while(0)
+#define spin_lock_irq(lock)    cli()
+#define spin_unlock_irq(lock)  sti()
+
+#define spin_lock_irqsave(lock, flags)         save_and_cli(flags)
+#define spin_unlock_irqrestore(lock, flags)    restore_flags(flags)
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED { }
+
+#define read_lock(lock)                do { } while(0)
+#define read_unlock(lock)      do { } while(0)
+#define write_lock(lock)       do { } while(0)
+#define write_unlock(lock)     do { } while(0)
+#define read_lock_irq(lock)    cli()
+#define read_unlock_irq(lock)  sti()
+#define write_lock_irq(lock)   cli()
+#define write_unlock_irq(lock) sti()
+
+#define read_lock_irqsave(lock, flags)         save_and_cli(flags)
+#define read_unlock_irqrestore(lock, flags)    restore_flags(flags)
+#define write_lock_irqsave(lock, flags)                save_and_cli(flags)
+#define write_unlock_irqrestore(lock, flags)   restore_flags(flags)
+
+#else
+
+#error "Nix SMP on MIPS"
+
+#endif /* SMP */
+#endif /* __ASM_MIPS_SPINLOCK_H */
index b3b69f3c64afca3a6d1482ad41f947dad59eee93..4a110338af62be0f09c6ccc3bfdb46e3bc6c1b1b 100644 (file)
 /*
  *  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 */
index 8d53c8bcf721f921c97836e921ddb644a443ff99..9b2f48ed9f289dadce86629c99c25a9a1bef2d9b 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/types.h>
 
-struct old_stat {
+struct __old_kernel_stat {
        unsigned int    st_dev;
        unsigned int    st_ino;
        unsigned int    st_mode;
@@ -21,7 +21,7 @@ struct old_stat {
        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;
index 3cae732066ae4cfc5750457893430f79a84d5502..500f6f1b667be3ed3a1967031bb0402f33bc0d97 100644 (file)
@@ -1,25 +1,40 @@
+/*
+ * Definitions for the statfs(2) call.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_STATFS_H
 #define __ASM_MIPS_STATFS_H
 
-typedef struct {
-       long    val[2];
-} fsid_t;
+#include <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 */
index ce0ae940ec220d048f42afc86b8278884ca3f280..2fb241775e1d6e2c1681f73f0fc9e41d6ec85583 100644 (file)
@@ -5,16 +5,15 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994, 1995  Waldorf Electronics
- * written by Ralf Baechle
+ * Copyright (c) 1994, 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_STRING_H
 #define __ASM_MIPS_STRING_H
 
 #define __HAVE_ARCH_STRCPY
-extern __inline__ char * strcpy(char * dest, const char *src)
+extern __inline__ char *strcpy(char *__dest, __const__ char *__src)
 {
-  char *xdest = dest;
+  char *__xdest = __dest;
 
   __asm__ __volatile__(
        ".set\tnoreorder\n\t"
@@ -26,43 +25,43 @@ extern __inline__ char * strcpy(char * dest, const char *src)
        "addiu\t%0,1\n\t"
        ".set\tat\n\t"
        ".set\treorder"
-       : "=r" (dest), "=r" (src)
-        : "0" (dest), "1" (src)
+       : "=r" (__dest), "=r" (__src)
+        : "0" (__dest), "1" (__src)
        : "$1","memory");
 
-  return xdest;
+  return __xdest;
 }
 
 #define __HAVE_ARCH_STRNCPY
-extern __inline__ char * strncpy(char *dest, const char *src, size_t n)
+extern __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n)
 {
-  char *xdest = dest;
+  char *__xdest = __dest;
 
-  if (n == 0)
-    return xdest;
+  if (__n == 0)
+    return __xdest;
 
   __asm__ __volatile__(
        ".set\tnoreorder\n\t"
        ".set\tnoat\n"
        "1:\tlbu\t$1,(%1)\n\t"
-       "subu\t%2,%2,1\n\t"
+       "subu\t%2,1\n\t"
        "sb\t$1,(%0)\n\t"
        "beqz\t$1,2f\n\t"
-       "addiu\t%0,%0,1\n\t"
+       "addiu\t%0,1\n\t"
        "bnez\t%2,1b\n\t"
-       "addiu\t%1,%1,1\n"
+       "addiu\t%1,1\n"
        "2:\n\t"
        ".set\tat\n\t"
-       ".set\treorder\n\t"
-        : "=r" (dest), "=r" (src), "=r" (n)
-        : "0" (dest), "1" (src), "2" (n)
+       ".set\treorder"
+        : "=r" (__dest), "=r" (__src), "=r" (__n)
+        : "0" (__dest), "1" (__src), "2" (__n)
         : "$1","memory");
 
-  return dest;
+  return __dest;
 }
 
 #define __HAVE_ARCH_STRCMP
-extern __inline__ int strcmp(const char * cs, const char * ct)
+extern __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct)
 {
   int __res;
 
@@ -76,22 +75,22 @@ extern __inline__ int strcmp(const char * cs, const char * ct)
        "addiu\t%1,1\n\t"
        "bnez\t%2,1b\n\t"
        "lbu\t%2,(%0)\n\t"
-#ifndef __R4000__
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
        "nop\n\t"
 #endif
        "move\t%2,$1\n"
        "2:\tsubu\t%2,$1\n"
        "3:\t.set\tat\n\t"
        ".set\treorder"
-       : "=d" (cs), "=d" (ct), "=d" (__res)
-       : "0" (cs), "1" (ct)
+       : "=r" (__cs), "=r" (__ct), "=r" (__res)
+       : "0" (__cs), "1" (__ct)
        : "$1");
 
   return __res;
 }
 
 #define __HAVE_ARCH_STRNCMP
-extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
+extern __inline__ int strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count)
 {
   char __res;
 
@@ -110,118 +109,50 @@ extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
        "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 */
index 8483c5408f9f50736cec04007412b12498a5ba3e..f0d13cfd5e51f879ed3f5858ac5ce99ed6cb951c 100644 (file)
@@ -19,6 +19,7 @@
 #define SETNAME                    1   /* set hostname                  */
 #define FLUSH_CACHE               3    /* writeback and invalidate caches */
 #define MIPS_FIXADE                7   /* control address error fixing  */
+#define MIPS_RDNVRAM              10   /* read NVRAM */
 #define MIPS_ATOMIC_SET                2001    /* atomically set variable       */
 
 #endif /* __ASM_MIPS_SYSMIPS_H */
index 353acf6ac6dd3869bdd4d591b841e344dfb60ee4..daf477459101558fd0c2539ec231ab799c98fead 100644 (file)
@@ -6,33 +6,73 @@
  * for more details.
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
+ * Modified further for R[236]000 by Paul M. Antoine, 1996
  */
 #ifndef __ASM_MIPS_SYSTEM_H
 #define __ASM_MIPS_SYSTEM_H
 
+#include <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"                        \
@@ -40,78 +80,71 @@ __asm__ __volatile__(                    \
        "nop\n\t"                        \
        ".set\tat\n\t"                   \
        ".set\treorder"                  \
-       : /* no outputs */               \
+       : "=r" (x)                       \
        : /* no inputs */                \
-       : "$1")
+       : "$1", "memory")
+
+extern void __inline__
+__restore_flags(int flags)
+{
+    __asm__ __volatile__(
+       ".set\tnoreorder\n\t"
+       "mtc0\t%0,$12\n\t"
+       "nop\n\t"
+       "nop\n\t"
+       "nop\n\t"
+       ".set\treorder"
+       : /* no output */
+       : "r" (flags)
+       : "memory");
+}
 
-#else /* !defined (__R4000__) */
 /*
- * Untested goodies for the R3000 based DECstation et al.
+ * Non-SMP versions ...
  */
-#define sti()                            \
-__asm__ __volatile__(                    \
-       ".set\tnoreorder\n\t"            \
-       ".set\tnoat\n\t"                 \
-       "mfc0\t$1,$12\n\t"               \
-       "ori\t$1,0x01\n\t"               \
-       "mtc0\t$1,$12\n\t"               \
-       ".set\tat\n\t"                   \
-       ".set\treorder"                  \
-       : /* no outputs */               \
-       : /* no inputs */                \
-       : "$1")
-
-#define cli()                            \
-__asm__ __volatile__(                    \
-       ".set\tnoreorder\n\t"            \
-       ".set\tnoat\n\t"                 \
-       "mfc0\t$1,$12\n\t"               \
-       "ori\t$1,1\n\t"                  \
-       "xori\t$1,1\n\t"                 \
-       "mtc0\t$1,$12\n\t"               \
-       ".set\tat\n\t"                   \
-       ".set\treorder"                  \
-       : /* no outputs */               \
-       : /* no inputs */                \
-       : "$1")
-#endif /* !defined (__R4000__) */
+#define sti() __sti()
+#define cli() __cli()
+#define save_flags(x) __save_flags(x)
+#define save_and_cli(x) __save_and_cli(x)
+#define restore_flags(x) __restore_flags(x)
 
-#define nop() __asm__ __volatile__ ("nop")
-
-#define save_flags(x)                    \
+#define sync_mem()                       \
 __asm__ __volatile__(                    \
        ".set\tnoreorder\n\t"            \
-       "mfc0\t%0,$12\n\t"               \
+       "sync\n\t"                       \
        ".set\treorder"                  \
-       : "=r" (x))                      \
+        : /* no output */                \
+       : /* no input */                 \
+       : "memory")
 
-#define restore_flags(x)                 \
-__asm__ __volatile__(                    \
-       ".set\tnoreorder\n\t"            \
-       "mtc0\t%0,$12\n\t"               \
-       "nop\n\t"                        \
-       "nop\n\t"                        \
-       "nop\n\t"                        \
-       ".set\treorder"                  \
-       : /* no output */                \
-       : "r" (x))                       \
+#if !defined (__LANGUAGE_ASSEMBLY__)
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern asmlinkage void (*resume)(void *tsk);
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
-#define sync_mem()                       \
-__asm__ __volatile__(                    \
-       ".set\tnoreorder\n\t"            \
-       "sync\n\t"                       \
-       ".set\treorder")                 \
+/*
+ * FIXME: resume() assumes current == prev
+ */
+#define switch_to(prev,next) \
+do { \
+       prev->tss.current_ds = active_ds; \
+        active_ds = next->tss.current_ds; \
+        resume(next); \
+} while(0)
 
 /*
  * The 8 and 16 bit variants have to disable interrupts temporarily.
  * Both are currently unused.
  */
-extern inline unsigned long xchg_u8(volatile char * m, unsigned long val)
+extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val)
 {
        unsigned long flags, retval;
 
        save_flags(flags);
-       sti();
+       cli();
        retval = *m;
        *m = val;
        restore_flags(flags);
@@ -119,12 +152,12 @@ extern inline unsigned long xchg_u8(volatile char * m, unsigned long val)
        return retval;
 }
 
-extern inline unsigned long xchg_u16(volatile short * m, unsigned long val)
+extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val)
 {
        unsigned long flags, retval;
 
        save_flags(flags);
-       sti();
+       cli();
        retval = *m;
        *m = val;
        restore_flags(flags);
@@ -136,8 +169,10 @@ extern inline unsigned long xchg_u16(volatile short * m, unsigned long val)
  * For 32 and 64 bit operands we can take advantage of ll and sc.
  * FIXME: This doesn't work for R3000 machines.
  */
-extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
+extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
+    (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
        unsigned long dummy;
 
        __asm__ __volatile__(
@@ -152,14 +187,23 @@ extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
                ".set\treorder"
                : "=r" (val), "=r" (m), "=r" (dummy)
                : "1" (m), "2" (val));
+#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */
+       unsigned long flags, retval;
+
+       save_flags(flags);
+       cli();
+       retval = *m;
+       *m = val;
+       restore_flags(flags);
 
+#endif /* Processor-dependent optimization */
        return val;
 }
 
 /*
  * Only used for 64 bit kernel.
  */
-extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
+extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val)
 {
        unsigned long dummy;
 
@@ -192,7 +236,7 @@ extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
  */
 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:
index 065d1d531c834639e0de23da9bb61ea62d70f217..5e46040893da5f04525355ce6050d5f258dd9a1a 100644 (file)
@@ -1,25 +1,26 @@
+/*
+ * termbits stuff for Linux/MIPS.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TERMBITS_H
 #define __ASM_MIPS_TERMBITS_H
 
-#include <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 */
@@ -32,4 +33,174 @@ struct termios {
        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 */
index df016414d7ef8d473f48780241e4e18613fefb7f..5dfb3a995a414bc4d3692dbf41cc0b825bc39b65 100644 (file)
@@ -1,8 +1,45 @@
+/*
+ * ioctls for Linux/MIPS.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TERMIOS_H
-#define __ASM_MIPS_TERMIOS_H
 
-#include <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;
@@ -11,15 +48,60 @@ struct winsize {
        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; \
@@ -31,24 +113,24 @@ do { \
        (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 */
index 30bb1904f82ca40b0beb7bf02c0cfd0235923946..4d27f768b18a655dd0e92db5a55f245b43aeb620 100644 (file)
@@ -5,36 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995 by Waldorf GMBH
- * written by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_TYPES_H
 #define __ASM_MIPS_TYPES_H
 
-#ifndef _SIZE_T
-#define _SIZE_T
-typedef __SIZE_TYPE__ size_t;
-#endif
-
-#ifndef _SSIZE_T
-#define _SSIZE_T
-typedef __SSIZE_TYPE__ ssize_t;
-#endif
-
-#ifndef _PTRDIFF_T
-#define _PTRDIFF_T
-typedef __PTRDIFF_TYPE__ ptrdiff_t;
-#endif
-
-#ifndef _TIME_T
-#define _TIME_T
-typedef long time_t;
-#endif
-
-#ifndef _CLOCK_T
-#define _CLOCK_T
-typedef long clock_t;
-#endif
+typedef unsigned long umode_t;
 
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
@@ -94,65 +70,4 @@ typedef unsigned long u64;
 
 #endif /* __KERNEL__ */
 
-typedef __s32 pid_t;
-typedef __s32 uid_t;
-typedef __s32 gid_t;
-typedef __u32 dev_t;
-typedef __u32 ino_t;
-typedef __u32 mode_t;
-typedef __u32 umode_t;
-typedef __u32 nlink_t;
-typedef long daddr_t;
-typedef long off_t;
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
-{ 
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(fd_set *p)
-{
-       unsigned int *tmp = p->fds_bits;
-       int i;
-
-       if (__builtin_constant_p(__FDSET_INTS)) {
-               switch (__FDSET_INTS) {
-                       case 8:
-                               tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
-                               tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
-                               return;
-               }
-       }
-       i = __FDSET_INTS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
-
 #endif /* __ASM_MIPS_TYPES_H */
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
new file mode 100644 (file)
index 0000000..b650209
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * include/asm-mips/uaccess.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_UACCESS_H
+#define __ASM_MIPS_UACCESS_H
+
+#include <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 */
diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h
new file mode 100644 (file)
index 0000000..ff78033
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Inline functions to do unaligned accesses.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_UNALIGNED_H
+#define __ASM_MIPS_UNALIGNED_H
+
+#include <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 */
index e570e8f9af384c864ff4fb10134dbd8d7d181ccd..4cf30a110eb6e1f042ee76f8e555733ae96d42fa 100644 (file)
@@ -5,16 +5,18 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ *
+ * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto
+ * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A
  */
 #ifndef __ASM_MIPS_UNISTD_H
 #define __ASM_MIPS_UNISTD_H
 
 /*
  * The syscalls 0 - 3999 are reserved for a down to the root syscall
- * compatibility with Risc/OS and IRIX.  None of these syscalls has yet been
- * implemented.  We'll see how to deal with the various "real" BSD variants
- * like Ultrix, NetBSD ...
+ * compatibility with RISC/os and IRIX.  We'll see how to deal with the
+ * various "real" BSD variants like Ultrix, NetBSD ...
  */
 
 /*
 #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__
 
@@ -1261,17 +1293,85 @@ 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" \
                   "move\t$7,%6\n\t" \
-                  "move\t$3,%7\n\t" \
+                 "subu\t$29,24\n\t" \
+                 "sw\t$2,16($29)\n\t" \
                  "li\t$2,%2\n\t" \
-                  "syscall" \
+                  "syscall\n\t" \
+                 "addiu\t$29,24" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)), \
+                                      "r" ((long)(c)), \
+                                      "r" ((long)(d)), \
+                                      "m" ((long)(e)) \
+                  : "$2","$4","$5","$6","$7"); \
+if (__err == 0) \
+       return (type) __res; \
+errno = __res; \
+return -1; \
+}
+
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
+{ \
+register long __res __asm__ ("$2"); \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                 "lw\t$2,%7\n\t" \
+                 "lw\t$3,%8\n\t" \
+                  "move\t$7,%6\n\t" \
+                 "subu\t$29,24\n\t" \
+                 "sw\t$2,16($29)\n\t" \
+                 "sw\t$3,20($29)\n\t" \
+                 "li\t$2,%2\n\t" \
+                  "syscall\n\t" \
+                 "addiu\t$29,24" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)), \
+                                      "r" ((long)(c)), \
+                                      "r" ((long)(d)), \
+                                      "m" ((long)(e)), \
+                                      "m" ((long)(f)) \
+                  : "$2","$3","$4","$5","$6","$7"); \
+if (__err == 0) \
+       return (type) __res; \
+errno = __res; \
+return -1; \
+}
+
+#define _syscall7(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f,gtype,g) \
+type name (atype a,btype b,ctype c,dtype d,etype e,ftype f,gtype g) \
+{ \
+register long __res __asm__ ("$2"); \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                 "lw\t$2,%7\n\t" \
+                 "lw\t$3,%8\n\t" \
+                  "move\t$7,%6\n\t" \
+                 "subu\t$29,32\n\t" \
+                 "sw\t$2,16($29)\n\t" \
+                 "lw\t$2,%9\n\t" \
+                 "sw\t$3,20($29)\n\t" \
+                 "sw\t$2,24($29)\n\t" \
+                 "li\t$2,%2\n\t" \
+                  "syscall\n\t" \
+                 "addiu\t$29,32" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)), \
-                                      "r" ((long)(e)) \
-                  : "$3","$4","$5","$6"); \
+                                      "m" ((long)(e)), \
+                                      "m" ((long)(f)), \
+                                      "m" ((long)(g)) \
+                  : "$2","$3","$4","$5","$6","$7"); \
 if (__err == 0) \
        return (type) __res; \
 errno = __res; \
@@ -1332,13 +1432,13 @@ static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long f
                "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)
index 64069dd60864c3d88e32ab36e121d6fb94261d10..e3747e88cd1931ceb01d4eaf85f3a7153b5bf1ea 100644 (file)
@@ -9,8 +9,8 @@
 /*
  * Core file format: The core file is written in such a way that gdb
  * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
- * are as follows:
+ * linux we use the `trad-core' bfd, NOT the irix-core).  The file
+ * contents are as follows:
  *
  *  upage: 1 page consisting of a user struct that tells gdb
  *     what is present in the file.  Directly after this is a
@@ -30,7 +30,7 @@
  *     to write an integer number of pages.
  */
 struct user {
-       unsigned long   regs[EF_SIZE/8+32];     /* integer and fp regs */
+       unsigned long   regs[EF_SIZE/4+64];     /* integer and fp regs */
        size_t          u_tsize;                /* text size (pages) */
        size_t          u_dsize;                /* data size (pages) */
        size_t          u_ssize;                /* stack size (pages) */
index e531f2370eba180b78a716f4382866fbf8187788..e3183b1de2ec9315de112a722e3920ced8f1a1b9 100644 (file)
@@ -5,19 +5,24 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_VECTOR_H
 #define __ASM_MIPS_VECTOR_H
 
+/*
+ * These vector structures are not very good to maintain - they'd probably
+ * grow to at leat three times the size - so I'll remove 'em and replace
+ * the with lots of ordinary variables.
+ */
+extern void (*irq_setup)(void);
+extern asmlinkage void (*fd_cacheflush)(const void *addr, size_t size);
+
 /*
  * This structure defines how to access various features of
  * different machine types and how to access them.
- *
- * FIXME: More things need to be accessed via this vector.
  */
 struct feature {
-       void (*handle_int)(void);
        /*
         * How to access the floppy controller's ports.
         */
@@ -37,25 +42,13 @@ struct feature {
        int (*fd_get_dma_residue)(void);
        void (*fd_enable_irq)(void);
        void (*fd_disable_irq)(void);
-       void (*fd_cacheflush)(unsigned char *addr, unsigned int size);
        /*
-        * How to access the RTC register of DS1287
+        * How to access the RTC register of the DS1287?
         */
-       unsigned char (*rtc_read_data)(void);
-       void (*rtc_write_data)(unsigned char);
-};
-
-/*
- * Similar to the above this is a structure that describes various
- * CPU dependent features.
- *
- * FIXME: This vector isn't being used yet
- */
-struct cpu {
-       int dummy;      /* keep GCC from complaining */
+       unsigned char (*rtc_read_data)(unsigned long addr);
+       void (*rtc_write_data)(unsigned char data, unsigned long addr);
 };
 
 extern struct feature *feature;
-extern struct cpu *cpu;
 
 #endif /* __ASM_MIPS_VECTOR_H */
diff --git a/include/asm-mips/watch.h b/include/asm-mips/watch.h
new file mode 100644 (file)
index 0000000..9c44856
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Functions to use the watch register debugging functionality.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ */
+#ifndef __ASM_WATCH_H
+#define __ASM_WATCH_H
+
+#include <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
index 52a3d45bd3434cc8ad42fce342ed16f0b07aaa76..f56e53db7db867c75a7f35fdc7405437f93ca963 100644 (file)
@@ -83,6 +83,8 @@
 #define TIOCGETD       0x5424
 #define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
 
 #define TIOCSERCONFIG  0x5453
 #define TIOCSERGWILD   0x5454
index 8b84e1dce12ada3b83ad9fa76775ec6b539b61e5..5b54f967ca638ba3b2c0edbbef5148493f6f55b9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.60 1997/04/14 17:05:16 jj Exp $ */
+/* $Id: pgtable.h,v 1.61 1997/06/06 10:56:34 jj Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -368,7 +368,7 @@ extern __inline__ void add_to_ctx_list(struct ctx_list *head, struct ctx_list *e
 #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){
index 70e6c37a40ddb33b975e4fa32eee61746dc1a221..e1fa6f88afd49f2bd125fd80fc1e4f602e48c12d 100644 (file)
 #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__ */
index 5060d88ae4a7198f0397a02ea62515f7ee17d0fb..f71f7e0e5c9a38167fd93cba44d071fe2cff6e2e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.16 1997/05/28 13:48:56 jj Exp $
+/* $Id: bitops.h,v 1.17 1997/06/14 17:35:05 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -260,22 +260,12 @@ extern __inline__ int test_le_bit(int nr, __const__ void * addr)
 #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;
 }
 
index 2325ef29c753cb162e2b696717eb76d52e8e9bab..dce2db2468135b2aaa521a1d2e34db10953ad5a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: byteorder.h,v 1.5 1997/05/28 11:35:41 jj Exp $ */
+/* $Id: byteorder.h,v 1.6 1997/06/14 17:35:07 davem Exp $ */
 #ifndef _SPARC64_BYTEORDER_H
 #define _SPARC64_BYTEORDER_H
 
@@ -56,21 +56,27 @@ extern __inline__ __u64 cpu_to_le64(__u64 value)
 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; }
index 9a43b6c3ff8364cc94947f79a483fd69874cf805..1cef89ff172bf28a653b1b029e0f977ee9c29487 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.6 1997/05/17 11:51:27 davem Exp $ */
+/* $Id: elf.h,v 1.7 1997/06/14 21:28:07 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
@@ -32,7 +32,9 @@ typedef unsigned long elf_fpregset_t;
 /*
  * 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
index 3d8713468b34d31f4549591b8ca123839d4b7340..1dd99a76135ef68ea08a9edb6d6b8ee1ca02d929 100644 (file)
@@ -48,10 +48,6 @@ struct  fbtype {
 };
 #define FBIOGTYPE _IOR('F', 0, struct fbtype)
 
-/* Used by FBIOPUTCMAP
- *
- * XXX 32-bit binary compatability item... -DaveM
- */
 struct  fbcmap {
         int             index;          /* first element (0 origin) */
         int             count;
@@ -104,7 +100,6 @@ struct fbcurpos {
 #define FB_CUR_SETSHAPE 0x10   /* set shape */
 #define FB_CUR_SETALL   0x1F   /* all of the above */
 
-/* XXX 32-bit binary compatability item... -DaveM */
 struct fbcursor {
         short set;              /* what to set, choose from the list above */
         short enable;           /* cursor on/off */
diff --git a/include/asm-sparc64/fs_mount.h b/include/asm-sparc64/fs_mount.h
deleted file mode 100644 (file)
index 3ad7ad6..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* $Id: fs_mount.h,v 1.2 1997/04/18 14:34:46 jj Exp $
- * fs_mount.h:  Definitions for mount structure conversions.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-#ifndef __ASM_FS_MOUNT_H
-#define __ASM_FS_MOUNT_H
-
-#if defined(CONFIG_SPARC32_COMPAT) || defined(CONFIG_SPARC32_COMPAT_MODULE)
-
-#include <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 */
index 62fe9a08f0f2bbe17060f8f003c3d82a7e53b2e2..7c6be4849643e9ad4c20143df081077f48ada585 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: head.h,v 1.22 1997/06/02 06:33:40 davem Exp $ */
+/* $Id: head.h,v 1.23 1997/06/14 13:25:50 davem Exp $ */
 #ifndef _SPARC64_HEAD_H
 #define _SPARC64_HEAD_H
 
 #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;
index 0432cb46ffd4ac3b8854e3859dc7fd8aaf19e89c..c0348eef1c52b9f329c67001cf7b0d242ea33a15 100644 (file)
@@ -1,14 +1,9 @@
-/* $Id: ioctls.h,v 1.2 1997/04/04 00:50:18 davem Exp $ */
+/* $Id: ioctls.h,v 1.3 1997/06/14 17:35:08 davem Exp $ */
 #ifndef _ASM_SPARC64_IOCTLS_H
 #define _ASM_SPARC64_IOCTLS_H
 
 #include <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)
@@ -24,7 +19,7 @@
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
- * thing we support some ioctls under Linux (autoconfiguration stuff)
+ * think we support some ioctls under Linux (autoconfiguration stuff)
  */
 /* Little t */
 #define TIOCGETD       _IOR('t', 0, int)
index 9a5b1045807f1414642812ab464905cd31c6ba12..008f68bc1edc14514b69cb89caf57b985e863a8d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.10 1997/05/23 09:35:55 jj Exp $ */
+/* $Id: mmu_context.h,v 1.11 1997/06/13 14:03:04 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -42,11 +42,11 @@ extern __inline__ void get_new_mmu_context(struct mm_struct *mm,
                        spitfire_put_itlb_data(entry, 0x0UL);
                }
                membar("#Sync");
-               flushi(PAGE_OFFSET);
+               __asm__ __volatile__("flush %g4");
                restore_flags(flags);
 
                ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
-               if(!ctx)
+               if(ctx == 1) /* _not_ zero! */
                        ctx = CTX_FIRST_VERSION;
        }
        tlb_context_cache = ctx + 1;
@@ -55,30 +55,32 @@ extern __inline__ void get_new_mmu_context(struct mm_struct *mm,
 
 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__) */
index 71679e351ef6dd07cdf7c3f9744474dd5ca40742..17a6ff611ed9d041209586ec63721f4e985ba395 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.8 1997/03/26 12:24:21 davem Exp $ */
+/* $Id: page.h,v 1.9 1997/06/14 21:28:09 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
 
 #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
index e56a4024df866906bbf71d35cd5457aacaec4c18..772121a2643775b1aaa663498427a489107494a1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.34 1997/06/02 06:33:41 davem Exp $
+/* $Id: pgtable.h,v 1.37 1997/06/13 14:03:06 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
 #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
@@ -244,7 +243,7 @@ extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
 1:
        stxa            %%g0, [%%g3] %3
        stxa            %%g0, [%%g3] %4
-       be,a,pt         %%icc, 1f
+       be,pt           %%icc, 1f
         nop
        stxa            %%g2, [%%g7] %2
 1:
@@ -268,7 +267,7 @@ extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start
                start &= PAGE_MASK;
                save_and_cli(flags);
                if(new_ctx != old_ctx)
-                       spitfire_set_secondary_context(mm->context);
+                       spitfire_set_secondary_context(new_ctx);
                while(start < end) {
                        spitfire_flush_dtlb_secondary_page(start);
                        spitfire_flush_itlb_secondary_page(start);
@@ -299,7 +298,7 @@ extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long
 1:
        stxa            %%g0, [%%g3] %3
        stxa            %%g0, [%%g3] %4
-       be,a,pt         %%icc, 1f
+       be,pt           %%icc, 1f
         nop
        stxa            %%g2, [%%g7] %2
 1:
@@ -638,7 +637,7 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 { 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))
@@ -651,16 +650,16 @@ sun4u_get_pte (unsigned long addr)
        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
index f58c9da70970c907e4a8fca05699a457e1a6639c..3cd62b8afd5e320310422f4bc1a2cfcf78af9628 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.27 1997/05/23 09:35:52 jj Exp $
+/* $Id: processor.h,v 1.29 1997/06/16 04:45:05 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -56,7 +56,8 @@ struct thread_struct {
        unsigned long sig_desc;
 
        struct sigstack sstk_info;
-       int current_ds, new_signal;
+       unsigned long current_ds;
+       unsigned long new_signal;
        
        struct pt_regs *kregs;
        
@@ -135,7 +136,7 @@ do { \
        "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)
 
index 5e7a7f8c12a78a6e740afe9ef3d46fdf6af9622d..b3aedd4ee8e16561a8487333f09426b09d14a2e2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.2 1997/04/04 00:50:27 davem Exp $
+/* $Id: resource.h,v 1.3 1997/06/14 17:35:09 davem Exp $
  * resource.h: Resource definitions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -25,7 +25,6 @@
 #define RLIM_NLIMITS   10
 
 #ifdef __KERNEL__
-/* XXX 32-bit binary compatability... */
 #define INIT_RLIMITS                                                   \
 {                                                                      \
     {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},                                \
index 9d35493d9e7ffc43c8ce9929ace1ad449c18dfcb..2e072c0c88090de60b6b66e2a99d1ef153285d7a 100644 (file)
@@ -1,14 +1,9 @@
-/* $Id: sigcontext.h,v 1.4 1997/04/04 00:50:28 davem Exp $ */
+/* $Id: sigcontext.h,v 1.6 1997/06/16 00:29:25 richard Exp $ */
 #ifndef __SPARC64_SIGCONTEXT_H
 #define __SPARC64_SIGCONTEXT_H
 
 #include <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__
@@ -47,12 +42,12 @@ struct sigcontext32 {
 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.
index d0d88fa5c8b41e4064e532b556d7bdbf18d507a4..c428fdcd9c46709b7e80c212142ac6a295b29d50 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.22 1997/06/01 10:27:28 davem Exp $ */
+/* $Id: system.h,v 1.23 1997/06/16 06:17:06 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
@@ -200,15 +200,15 @@ extern __inline__ unsigned long xchg_u64(__volatile__ unsigned long *m,
 {
        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;
 }
 
index 40ad3ee21c7a81c57a91848361b0aa1f5c1eb622..460ccc11c1d4607fb5076386ca28579f8951aeab 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.13 1997/05/29 12:45:04 jj Exp $ */
+/* $Id: uaccess.h,v 1.14 1997/06/13 14:03:11 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
  *
  * "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)
index cb17f1888551bd0526ac8a44aafeb269df390697..27afe645edc6c22914d06af18550240d3429a1ac 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.5 1997/05/21 10:21:57 jj Exp $ */
+/* $Id: unistd.h,v 1.7 1997/06/16 05:37:44 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
 #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                              */
@@ -467,6 +467,7 @@ static __inline__ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned lo
 
 #endif /* __KERNEL_SYSCALLS__ */
 
+#ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
 #define   _SC_ARG_MAX             1
 #define   _SC_CHILD_MAX           2
@@ -476,5 +477,6 @@ static __inline__ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned lo
 #define   _SC_JOB_CONTROL         6
 #define   _SC_SAVED_IDS           7
 #define   _SC_VERSION             8
+#endif
 
 #endif /* _SPARC64_UNISTD_H */
index 668abd39115b9fa2da436a9c9316076496310d5d..ddc349d3ea1db195bf0360dd13b3df8541da8132 100644 (file)
@@ -185,18 +185,16 @@ typedef char buffer_block[BLOCK_SIZE];
  */
 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) */
@@ -797,9 +795,9 @@ extern inline blocking struct inode * get_empty_inode(void)
  */
 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);
index 5f18a049afced030cd52fcc54fd640220bf25237..c93764cb7cf4a991b268d0f08fe03d0438dc3456 100644 (file)
@@ -47,6 +47,8 @@
 #define ARPHRD_ROSE    270
 #define ARPHRD_X25     271             /* CCITT X.25                   */
 #define ARPHRD_PPP     512
+#define ARPHRD_HDLC    513             /* (Cisco) HDLC                 */
+#define ARPHRD_LAPB    516             /* LAPB                         */
 
 #define ARPHRD_TUNNEL  768             /* IPIP tunnel                  */
 #define ARPHRD_TUNNEL6 769             /* IPIP6 tunnel                 */
index bd30d7804e01ca1de840f6ec192350a3bf6b50e3..82a4b7570bbf4842d504abff48f0e1c5d53c9d2d 100644 (file)
@@ -136,5 +136,8 @@ extern int          sock_sendmsg(struct socket *, struct msghdr *m, int len);
 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 */
index b2706ce031b7a98f9f353831f17c79468bf5dc70..7be5e989805bd8b64389e865b7134f56c79ab08d 100644 (file)
@@ -55,6 +55,8 @@ extern void get_random_bytes(void *buf, int nbytes);
 
 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;
index 189194a49ba295f30440e3275bef0d05259549de..9346ab2a77fe8d36feec272c3cb4d171f60d1351 100644 (file)
@@ -519,12 +519,10 @@ extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue
 {
        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;
 }
index 08be132213bad8f7c8c904d1bc23154d572820dd..21a01f013c2e063c30a7ce8b30b4576eb723aac3 100644 (file)
@@ -32,7 +32,7 @@ typedef struct kmem_cache_s kmem_cache_t;
 #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
index 2ec41aa053774ae892c63b7cbc3960e3bfbee134..75fdf6c3d0f3cc5b569fcebddc41802dd897f869 100644 (file)
@@ -173,6 +173,7 @@ enum
        NET_IPV4_IGMP_AGE_THRESHOLD,
        NET_TCP_SYNCOOKIES,
        NET_TCP_ALWAYS_SYNCOOKIE,
+       NET_TCP_STDURG,
 };
 
 
index cedc7f3b10407a1d8757c5b29accf995e76c244b..d0f812e4d3bf64184c92e026c04f6ca580703f91 100644 (file)
@@ -281,15 +281,17 @@ struct tcp_func {
 
        int                     (*conn_request)         (struct sock *sk,
                                                         struct sk_buff *skb,
-                                                        void *opt,
-                                                        __u32 isn);
+                                                        void *opt, __u32 isn);
 
        struct sock *           (*syn_recv_sock)        (struct sock *sk,
                                                         struct sk_buff *skb,
-                                                        struct open_request *req);
+                                                        struct open_request *req,
+                                                        struct dst_entry *dst);
        
+#if 0
        __u32                   (*init_sequence)        (struct sock *sk,
                                                         struct sk_buff *skb);
+#endif
 
        struct sock *           (*get_sock)             (struct sk_buff *skb,
                                                         struct tcphdr *th);
@@ -385,7 +387,8 @@ extern int                  tcp_recvmsg(struct sock *sk,
                                            int len, int nonblock, 
                                            int flags, int *addr_len);
 
-extern void                    tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp);
+extern void                    tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, 
+                                                                         int no_fancy);
 
 /*
  *     TCP v4 functions exported for the inet6 API
@@ -407,7 +410,8 @@ extern int                  tcp_v4_conn_request(struct sock *sk,
 
 extern struct sock *           tcp_v4_syn_recv_sock(struct sock *sk,
                                                     struct sk_buff *skb,
-                                                    struct open_request *req);
+                                                    struct open_request *req,
+                                                       struct dst_entry *dst);
 
 extern int                     tcp_v4_do_rcv(struct sock *sk,
                                              struct sk_buff *skb);
@@ -417,6 +421,12 @@ extern int                 tcp_v4_connect(struct sock *sk,
                                               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 *);
@@ -522,7 +532,6 @@ static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
        return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
 }
 
-
 #undef STATE_TRACE
 
 #ifdef STATE_TRACE
index 8e5607e1e268e47a3260adcf4fc55ccf93c3a327..8bd9d269dd659026a097e683d290f9db9e428654 100644 (file)
@@ -341,6 +341,7 @@ EXPORT_SYMBOL(set_writetime);
 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);
index ca3d1780731d7f60515e3b7b5bfa3606ee264fc3..691d2b10bc304fc0dcf2f5f8b5baca13da501389 100644 (file)
@@ -612,21 +612,17 @@ asmlinkage int sys_setuid(uid_t uid)
  */
 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
-       uid_t old_ruid, old_euid, old_suid;
-
-       old_ruid = current->uid;
-       old_euid = current->euid;
-       old_suid = current->suid;
-
-       if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
-           (ruid != current->euid) && (ruid != current->suid))
-               return -EPERM;
-       if ((euid != (uid_t) -1) && (euid != current->uid) &&
-           (euid != current->euid) && (euid != current->suid))
-               return -EPERM;
-       if ((suid != (uid_t) -1) && (suid != current->uid) &&
-           (suid != current->euid) && (suid != current->suid))
-               return -EPERM;
+       if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+               if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
+                   (ruid != current->euid) && (ruid != current->suid))
+                       return -EPERM;
+               if ((euid != (uid_t) -1) && (euid != current->uid) &&
+                   (euid != current->euid) && (euid != current->suid))
+                       return -EPERM;
+               if ((suid != (uid_t) -1) && (suid != current->uid) &&
+                   (suid != current->euid) && (suid != current->suid))
+                       return -EPERM;
+       }
        if (ruid != (uid_t) -1) {
                /* See above commentary about NPROC rlimit issues here. */
                charge_uid(current, -1);
@@ -634,8 +630,12 @@ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
                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;
@@ -652,6 +652,46 @@ asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
        return retval;
 }
 
+/*
+ * Same as above, but for rgid, egid, sgid.
+ */
+asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+       if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+               if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
+                   (rgid != current->egid) && (rgid != current->sgid))
+                       return -EPERM;
+               if ((egid != (gid_t) -1) && (egid != current->gid) &&
+                   (egid != current->egid) && (egid != current->sgid))
+                       return -EPERM;
+               if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
+                   (sgid != current->egid) && (sgid != current->sgid))
+                       return -EPERM;
+       }
+       if (rgid != (gid_t) -1)
+               current->gid = rgid;
+       if (egid != (gid_t) -1) {
+               if (egid != current->egid)
+                       current->dumpable = 0;
+               current->egid = egid;
+               current->fsgid = egid;
+       }
+       if (sgid != (gid_t) -1)
+               current->sgid = sgid;
+       return 0;
+}
+
+asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
+{
+       int retval;
+
+       if (!(retval = put_user(current->gid, rgid)) &&
+           !(retval = put_user(current->egid, egid)))
+               retval = put_user(current->sgid, sgid);
+
+       return retval;
+}
+
 
 /*
  * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
index ad159bc2c76208d23428786b02643c906b4ca58c..b79c7165695cfad83e8bd352a2fcdd4a44b2086c 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
  *                       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)
@@ -215,9 +215,9 @@ typedef struct kmem_bufctl_s {
 #define        SLAB_RED_MAGIC1         0x5A2CF071UL    /* when obj is active */
 #define        SLAB_RED_MAGIC2         0x170FC2A5UL    /* when obj is inactive */
 
-/* ...and for poisioning */
-#define        SLAB_POISION_BYTE       0x5a            /* byte value for poisioning */
-#define        SLAB_POISION_END        0xa5            /* end-byte of poisioning */
+/* ...and for poisoning */
+#define        SLAB_POISON_BYTE        0x5a            /* byte value for poisoning */
+#define        SLAB_POISON_END 0xa5            /* end-byte of poisoning */
 
 #endif /* SLAB_DEBUG_SUPPORT */
 
@@ -546,17 +546,17 @@ kmem_freepages(kmem_cache_t *cachep, void *addr)
 
 #if    SLAB_DEBUG_SUPPORT
 static inline void
-kmem_poision_obj(kmem_cache_t *cachep, void *addr)
+kmem_poison_obj(kmem_cache_t *cachep, void *addr)
 {
-       memset(addr, SLAB_POISION_BYTE, cachep->c_org_size);
-       *(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISION_END;
+       memset(addr, SLAB_POISON_BYTE, cachep->c_org_size);
+       *(unsigned char *)(addr+cachep->c_org_size-1) = SLAB_POISON_END;
 }
 
 static inline int
-kmem_check_poision_obj(kmem_cache_t *cachep, void *addr)
+kmem_check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
        void *end;
-       end = memchr(addr, SLAB_POISION_END, cachep->c_org_size);
+       end = memchr(addr, SLAB_POISON_END, cachep->c_org_size);
        if (end != (addr+cachep->c_org_size-1))
                return 1;
        return 0;
@@ -605,7 +605,7 @@ kmem_slab_destroy(kmem_cache_t *cachep, kmem_slab_t *slabp)
 {
        if (cachep->c_dtor
 #if    SLAB_DEBUG_SUPPORT
-               || cachep->c_flags & (SLAB_POISION || SLAB_RED_ZONE)
+               || cachep->c_flags & (SLAB_POISON || SLAB_RED_ZONE)
 #endif /*SLAB_DEBUG_SUPPORT*/
        ) {
                /* Doesn't use the bufctl ptrs to find objs. */
@@ -629,10 +629,10 @@ kmem_slab_destroy(kmem_cache_t *cachep, kmem_slab_t *slabp)
 #endif /*SLAB_DEBUG_SUPPORT*/
                                (cachep->c_dtor)(objp, cachep, 0);
 #if    SLAB_DEBUG_SUPPORT
-                       else if (cachep->c_flags & SLAB_POISION) {
-                               if (kmem_check_poision_obj(cachep, objp))
+                       else if (cachep->c_flags & SLAB_POISON) {
+                               if (kmem_check_poison_obj(cachep, objp))
                                        printk(KERN_ERR "kmem_slab_destory: "
-                                              "Bad poision - %s\n", cachep->c_name);
+                                              "Bad poison - %s\n", cachep->c_name);
                        }
                        if (cachep->c_flags & SLAB_RED_ZONE)
                                objp -= BYTES_PER_WORD;
@@ -726,18 +726,18 @@ kmem_cache_create(const char *name, size_t size, size_t offset,
                flags &= ~SLAB_DEBUG_INITIAL;
        }
 
-       if ((flags & SLAB_POISION) && ctor) {
-               /* request for poisioning, but we can't do that with a constructor */
-               printk("%sPoisioning requested, but con given - %s\n", func_nm, name);
-               flags &= ~SLAB_POISION;
+       if ((flags & SLAB_POISON) && ctor) {
+               /* request for poisoning, but we can't do that with a constructor */
+               printk("%sPoisoning requested, but con given - %s\n", func_nm, name);
+               flags &= ~SLAB_POISON;
        }
 #if    0
        if ((flags & SLAB_HIGH_PACK) && ctor) {
                printk("%sHigh pack requested, but con given - %s\n", func_nm, name);
                flags &= ~SLAB_HIGH_PACK;
        }
-       if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISION|SLAB_RED_ZONE))) {
-               printk("%sHigh pack requested, but with poisioning/red-zoning - %s\n",
+       if ((flags & SLAB_HIGH_PACK) && (flags & (SLAB_POISON|SLAB_RED_ZONE))) {
+               printk("%sHigh pack requested, but with poisoning/red-zoning - %s\n",
                       func_nm, name);
                flags &= ~SLAB_HIGH_PACK;
        }
@@ -1094,9 +1094,9 @@ kmem_cache_init_objs(kmem_cache_t * cachep, kmem_slab_t * slabp, void *objp,
                if (cachep->c_ctor)
                        cachep->c_ctor(objp, cachep, ctor_flags);
 #if    SLAB_DEBUG_SUPPORT
-               else if (cachep->c_flags & SLAB_POISION) {
-                       /* need to poision the objs */
-                       kmem_poision_obj(cachep, objp);
+               else if (cachep->c_flags & SLAB_POISON) {
+                       /* need to poison the objs */
+                       kmem_poison_obj(cachep, objp);
                }
 
                if (cachep->c_flags & SLAB_RED_ZONE) {
@@ -1386,7 +1386,7 @@ ret_obj:
                        bufp->buf_slabp = slabp;
                        objp = ((void*)bufp) - cachep->c_offset;
 finished:
-                       /* The lock is not needed by the red-zone or poision ops, and the
+                       /* The lock is not needed by the red-zone or poison ops, and the
                         * obj has been removed from the slab.  Should be safe to drop
                         * the lock here.
                         */
@@ -1395,8 +1395,8 @@ finished:
                        if (cachep->c_flags & SLAB_RED_ZONE)
                                goto red_zone;
 ret_red:
-                       if ((cachep->c_flags & SLAB_POISION) && kmem_check_poision_obj(cachep, objp))
-                               kmem_report_alloc_err("Bad poision", cachep);
+                       if ((cachep->c_flags & SLAB_POISON) && kmem_check_poison_obj(cachep, objp))
+                               kmem_report_alloc_err("Bad poison", cachep);
 #endif /* SLAB_DEBUG_SUPPORT */
                        return objp;
                }
@@ -1514,10 +1514,10 @@ passed_extra:
                                /* (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);
@@ -1860,7 +1860,7 @@ kmem_self_test(void)
        kmem_cache_t    *test_cachep;
 
        printk(KERN_INFO "kmem_test() - start\n");
-       test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISION, NULL, NULL);
+       test_cachep = kmem_cache_create("test-cachep", 16, 0, SLAB_RED_ZONE|SLAB_POISON, NULL, NULL);
        if (test_cachep) {
                char *objp = kmem_cache_alloc(test_cachep, SLAB_KERNEL);
                if (objp) {
@@ -1869,12 +1869,12 @@ kmem_self_test(void)
                        *(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);
                }
index de05f70473ee22cbf462daba48ffddb8842b75e8..1f690a66236ed087acf879f8b58b3829eb4f63fe 100644 (file)
@@ -1540,11 +1540,33 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
                        ddp_dl->header_length + ddp->deh_len));
 
                *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));         /* Mend the byte order */
+
                /*
                 *      Send the buffer onwards
                 */
 
-               skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+               /*
+                *      Now we must always be careful. If it's come from 
+                *      localtalk to ethertalk it might not fit
+                *
+                *      Order matters here: If a packet has to be copied
+                *      to make a new headroom (rare hopefully) then it
+                *      won't need unsharing.
+                *
+                *      Note. ddp-> becomes invalid at the realloc.
+                */
+               
+               if(skb_headroom(skb)<22)
+                       /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
+                       skb=skb_realloc_headroom(skb, 32);
+               else
+                       skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+               
+               /*
+                *      If the buffer didnt vanish into the lack of
+                *      space bitbucket we can send it.
+                */
+                
                if(skb)
                {
                        skb->arp = 1;   /* Resolved */
@@ -1702,10 +1724,14 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len,
                        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
        {
index 4895989946e1819dee9a402104808a2773a7a15d..3a5ac3b04590d4e5b5168a277faf41c54f1bd41e 100644 (file)
@@ -31,6 +31,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     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
index 9ce538dc41a936ecb13eac6b682e8d5729929751..2428ccc55f57e5323a7337d2f0bd7ffc61ded5a0 100644 (file)
@@ -52,6 +52,11 @@ else
   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)
index db54b567a4c5288060ef443743400f52fb358938..0d51af255d7d775c3cffb8703d09c9b9b34c150e 100644 (file)
@@ -388,7 +388,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len)
                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);
index 4a4c5321ccee2e59d50bb9dfad01ec908cf0a638..b55fb766608fbbc3fa74d04e95a79ebecb2f648f 100644 (file)
@@ -45,6 +45,7 @@
  *             Pavel Krauz     :       Limited broadcast fixed
  *     Alexey Kuznetsov        :       End of old history. Splitted to fib.c and
  *                                     route.c and rewritten from scratch.
+ *             Andi Kleen      :       Load-limit warning messages.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -568,7 +569,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
        return;
 
 reject_redirect:
-       if (ipv4_config.log_martians)
+       if (ipv4_config.log_martians && net_ratelimit())
                printk(KERN_INFO "Redirect from %lX/%s to %lX ignored."
                       "Path = %lX -> %lX, tos %02x\n",
                       ntohl(old_gw), dev->name, ntohl(new_gw),
@@ -636,7 +637,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
        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);
        }
@@ -1083,12 +1084,12 @@ no_route:
         *      Do not cache martian addresses: they should be logged (RFC1812)
         */
 martian_destination:
-       if (ipv4_config.log_martians)
+       if (ipv4_config.log_martians && net_ratelimit())
                printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
        return -EINVAL;
 
 martian_source:
-       if (ipv4_config.log_martians) {
+       if (ipv4_config.log_martians && net_ratelimit()) {
                /*
                 *      RFC1812 recommenadtion, if source is martian,
                 *      the only hint is MAC header.
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
new file mode 100644 (file)
index 0000000..35b3112
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  Syncookies implementation for the Linux kernel
+ *
+ *  Copyright (C) 1997 Andi Kleen
+ *  Based on ideas by D.J.Bernstein and Eric Schenk. 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ * 
+ *  $Id: syncookies.c,v 1.1 1997/06/06 20:37:56 freitag Exp $
+ *
+ *  Missing: IPv6 support. 
+ *           Some counter so that the Administrator can see when the machine
+ *           is under a syn flood attack.
+ */
+
+#include <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
index 6d7ba591fe4898dc5596eff3dfeff1b23dfa233b..5f804f3431fd48497040fc648d73e0c7525cc0ac 100644 (file)
@@ -60,8 +60,8 @@ extern int sysctl_tcp_retries2;
 extern int sysctl_tcp_max_delay_acks;
 extern int sysctl_tcp_fin_timeout;
 extern int sysctl_tcp_syncookies;
-extern int sysctl_tcp_always_syncookie;
 extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_stdurg; 
 
 extern int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp,
                                void *buffer, size_t *lenp);
@@ -203,10 +203,12 @@ ctl_table ipv4_table[] = {
        {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}
 };
 
index 604bd1c84c5f513e1fbe61774db3ecd3941fc61b..d74d330a949f2e2446b4aa6c629550ecfe8530d2 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.52 1997/05/31 12:36:42 freitag Exp $
+ * Version:    $Id: tcp_input.c,v 1.53 1997/06/06 20:38:00 freitag Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -65,6 +65,7 @@ int sysctl_tcp_window_scaling;
 int sysctl_tcp_syncookies; 
 int sysctl_tcp_always_syncookie;
 int sysctl_tcp_max_delay_acks = MAX_DELAY_ACK;
+int sysctl_tcp_stdurg;
 
 static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
 
@@ -288,7 +289,7 @@ static int tcp_reset(struct sock *sk, struct sk_buff *skb)
  *     FIXME: surely this can be more efficient. -- erics
  */
  
-void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp)
+void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp, int no_fancy)
 {
        unsigned char *ptr;
        int length=(th->doff*4)-sizeof(struct tcphdr);
@@ -323,21 +324,21 @@ void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp)
                                                break;
                                        case TCPOPT_WINDOW:
                                                if(opsize==TCPOLEN_WINDOW && th->syn)
-                                                       if (sysctl_tcp_window_scaling) {
+                                                       if (!no_fancy && sysctl_tcp_window_scaling) {
                                                                tp->wscale_ok = 1;
                                                                tp->snd_wscale = *(__u8 *)ptr;
                                                        }
                                                break;
                                        case TCPOPT_SACK_PERM:
                                                if(opsize==TCPOLEN_SACK_PERM && th->syn)
-                                                       if (sysctl_tcp_sack)
+                                                       if (sysctl_tcp_sack && !no_fancy)
                                                                tp->sack_ok = 1;
                                        case TCPOPT_TIMESTAMP:
                                                if(opsize==TCPOLEN_TIMESTAMP) {
                                                        /* Cheaper to set again then to
                                                         * test syn. Optimize this?
                                                         */
-                                                       if (sysctl_tcp_timestamps)
+                                                       if (sysctl_tcp_timestamps && !no_fancy)
                                                                tp->tstamp_ok = 1;
                                                        tp->saw_tstamp = 1;
                                                        tp->rcv_tsval = ntohl(*(__u32 *)ptr);
@@ -345,6 +346,8 @@ void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp)
                                                }
                                                break;
                                        case TCPOPT_SACK:
+                                               if (no_fancy) 
+                                                       break; 
                                                tp->sacks = (opsize-2)>>3;
                                                if (tp->sacks<<3 == opsize-2) {
                                                        int i;
@@ -385,7 +388,7 @@ static __inline__ int tcp_fast_parse_options(struct tcphdr *th, struct tcp_opt *
                        return 1;
                }
        }
-       tcp_parse_options(th,tp);
+       tcp_parse_options(th,tp,0);
        return 1;
 }
 
@@ -1233,7 +1236,7 @@ static __inline__ void tcp_ack_snd_check(struct sock *sk)
  *     place. We handle URGent data wrong. We have to - as
  *     BSD still doesn't use the correction from RFC961.
  *     For 1003.1g we should support a new option TCP_STDURG to permit
- *     either form.
+ *     either form (or just set the sysctl tcp_stdurg).
  */
  
 static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
@@ -1241,7 +1244,7 @@ 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);
 
@@ -1459,13 +1462,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                /* These use the socket TOS.. 
                 * might want to be the received TOS 
                 */
-               if(th->ack)
+               if(th->ack)  
                        return 1; /* send reset */
                
                if(th->syn) {
-                       __u32 isn = tp->af_specific->init_sequence(sk, skb);
-
-                       if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0)
+                       if(tp->af_specific->conn_request(sk, skb, opt, 0) < 0)
                                return 1;
 
                        /* Now we have several options: In theory there is 
@@ -1531,7 +1532,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                        tp->fin_seq = skb->seq;
 
                        tcp_set_state(sk, TCP_ESTABLISHED);
-                       tcp_parse_options(th,tp);
+                       tcp_parse_options(th,tp,0);
                        /* FIXME: need to make room for SACK still */
                        if (tp->wscale_ok == 0) {
                                tp->snd_wscale = tp->rcv_wscale = 0;
@@ -1574,7 +1575,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                 * tcp_connect.
                                 */
                                tcp_set_state(sk, TCP_SYN_RECV);
-                               tcp_parse_options(th,tp);
+                               tcp_parse_options(th,tp,0);
                                if (tp->saw_tstamp) {
                                        tp->ts_recent = tp->rcv_tsval;
                                        tp->ts_recent_stamp = jiffies;
@@ -1616,6 +1617,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                         sk->shutdown = SHUTDOWN_MASK;
 
                        isn = tp->rcv_nxt + 128000;
+                       if (isn == 0)  
+                               isn++; 
 
                        sk = tp->af_specific->get_sock(skb, th);
 
@@ -1710,8 +1713,10 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                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:
index c4d12a54faac0fb0202d111fb3f57c37408ab686..8115e819ae2cf11b9dfeb39c39254f27c1a434a7 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.43 1997/05/06 09:31:44 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.49 1997/06/09 13:27:35 freitag Exp $
  *
  *             IPv4 specific functions
  *
@@ -30,6 +30,9 @@
  *             David S. Miller :       Change semantics of established hash,
  *                                     half is devoted to TIME_WAIT sockets
  *                                     and the rest go in the other half.
+ *             Andi Kleen :            Add support for syncookies and fixed
+ *                                     some bugs: ip options weren't passed to
+ *                                     the TCP layer, missed a check for an ACK bit.
  */
 
 #include <linux/config.h>
@@ -48,6 +51,7 @@ extern int sysctl_tcp_sack;
 extern int sysctl_tcp_tsack;
 extern int sysctl_tcp_timestamps;
 extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_syncookies;
 
 static void tcp_v4_send_reset(struct sk_buff *skb);
 
@@ -403,7 +407,7 @@ struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
 
 #endif
 
-static __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
 {
        return secure_tcp_sequence_number(sk->saddr, sk->daddr,
                                          skb->h.th->dest,
@@ -835,6 +839,8 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req)
 
        /* Don't offer more than they did.
         * This way we don't have to memorize who said what.
+        * FIXME: maybe this should be changed for better performance
+        * with syncookies.
         */
        req->mss = min(mss, req->mss);
 
@@ -891,17 +897,13 @@ static void tcp_v4_or_free(struct open_request *req)
                        sizeof(struct ip_options) + req->af.v4_req.opt->optlen);
 }
 
-static struct or_calltable or_ipv4 = {
+struct or_calltable or_ipv4 = {
        tcp_v4_send_synack,
        tcp_v4_or_free
 };
 
-static int tcp_v4_syn_filter(struct sock *sk, struct sk_buff *skb, __u32 saddr)
-{
-       return 0;
-}
-
-int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn)
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, 
+                                               __u32 isn)
 {
        struct ip_options *opt = (struct ip_options *) ptr;
        struct tcp_opt tp;
@@ -909,23 +911,39 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i
        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();
@@ -934,15 +952,12 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i
                goto exit;
        }
 
-       sk->ack_backlog++;
-
        req->rcv_wnd = 0;               /* So that tcp_send_synack() knows! */
 
        req->rcv_isn = skb->seq;
-       req->snt_isn = isn;
-       tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
+       tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
        tp.in_mss = 536;
-       tcp_parse_options(th,&tp);
+       tcp_parse_options(th,&tp, want_cookie);
        if (tp.saw_tstamp)
                req->ts_recent = tp.rcv_tsval;
        req->mss = tp.in_mss;
@@ -954,8 +969,17 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i
        req->af.v4_req.loc_addr = daddr;
        req->af.v4_req.rmt_addr = saddr;
 
+       /* Note that we ignore the isn passed from the TIME_WAIT
+        * state here. That's the price we pay for cookies.
+        */
+       if (want_cookie)
+               isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+
+       req->snt_isn = isn;
+
        /* IPv4 options */
        req->af.v4_req.opt = NULL;
+
        if (opt && opt->optlen) {
                int opt_size = sizeof(struct ip_options) + opt->optlen;
 
@@ -973,36 +997,50 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i
 
        tcp_v4_send_synack(sk, req);
 
-       req->expires = jiffies + TCP_TIMEOUT_INIT;
-       tcp_inc_slow_timer(TCP_SLT_SYNACK);
-       tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);
+       if (want_cookie) {
+               if (req->af.v4_req.opt) 
+                       kfree(req->af.v4_req.opt); 
+               tcp_openreq_free(req); 
+       } else  {
+               req->expires = jiffies + TCP_TIMEOUT_INIT;
+               tcp_inc_slow_timer(TCP_SLT_SYNACK);
+               tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);
+       }
 
        sk->data_ready(sk, 0);
 
 exit:
        kfree_skb(skb, FREE_READ);
        return 0;
+
+dead:
+       SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk);
+       tcp_statistics.TcpAttemptFails++;
+       return -ENOTCONN;
 }
 
 struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-                                  struct open_request *req)
+                                  struct open_request *req,
+                                  struct dst_entry *dst)
 {
        struct tcp_opt *newtp;
        struct sock *newsk;
-       struct rtable *rt;
        int snd_mss;
 
        newsk = sk_alloc(GFP_ATOMIC);
-       if (newsk == NULL)
+       if (newsk == NULL) {
+               if (dst) 
+                       dst_release(dst);
                return NULL;
+       }
 
        memcpy(newsk, sk, sizeof(*newsk));
 
        /* Or else we die! -DaveM */
        newsk->sklist_next = NULL;
 
-       newsk->opt = NULL;
-       newsk->dst_cache  = NULL;
+       newsk->opt = req->af.v4_req.opt;
+
        skb_queue_head_init(&newsk->write_queue);
        skb_queue_head_init(&newsk->receive_queue);
        skb_queue_head_init(&newsk->out_of_order_queue);
@@ -1072,17 +1110,21 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        newsk->rcv_saddr = req->af.v4_req.loc_addr;
 
        /* options / mss / route_cache */
-       newsk->opt = req->af.v4_req.opt;
-       if (ip_route_output(&rt,
-                           newsk->opt && newsk->opt->srr ? newsk->opt->faddr : newsk->daddr,
-                           newsk->saddr, newsk->ip_tos, NULL)) {
-               kfree(newsk);
-               return NULL;
-       }
-
-       newsk->dst_cache = &rt->u.dst;
-
-       snd_mss = rt->u.dst.pmtu;
+       if (dst == NULL) { 
+               struct rtable *rt;
+               
+               if (ip_route_output(&rt,
+                                   newsk->opt && newsk->opt->srr ? 
+                                   newsk->opt->faddr : newsk->daddr,
+                                   newsk->saddr, newsk->ip_tos, NULL)) {
+                       kfree(newsk);
+                       return NULL;
+               }
+               dst = &rt->u.dst;
+       } 
+       newsk->dst_cache = dst;
+       
+       snd_mss = dst->pmtu;
 
        /* FIXME: is mtu really the same as snd_mss? */
        newsk->mtu = snd_mss;
@@ -1124,7 +1166,7 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        return newsk;
 }
 
-struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
+static inline struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
 {
        struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
        struct open_request *req = tp->syn_wait_queue;
@@ -1133,8 +1175,13 @@ struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
         *      as we checked the user count on tcp_rcv and we're
         *      running from a soft interrupt.
         */
-       if(!req)
+       if(!req) {
+#ifdef CONFIG_SYN_COOKIES
+               goto checkcookie; 
+#else
                return sk;
+#endif
+       }
 
        while(req) {
                if (req->af.v4_req.rmt_addr == skb->nh.iph->saddr &&
@@ -1147,7 +1194,7 @@ struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
                                 *      yet accepted()...
                                 */
                                sk = req->sk;
-                               break;
+                               goto ende;
                        }
 
                        /* Check for syn retransmission */
@@ -1161,20 +1208,28 @@ struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
                                return NULL;
                        }
 
-                       sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+                       if (!skb->h.th->ack)
+                               return sk; 
+
+                       sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
                        tcp_dec_slow_timer(TCP_SLT_SYNACK);
                        if (sk == NULL)
                                return NULL;
 
                        req->expires = 0UL;
                        req->sk = sk;
-                       break;
+                       goto ende;
                }
                req = req->dl_next;
        }
 
-       skb_orphan(skb);
-       skb_set_owner_r(skb, sk);
+#ifdef CONFIG_SYN_COOKIES
+checkcookie:       
+       sk = cookie_v4_check(sk, skb, opt);
+#endif
+ende:  skb_orphan(skb);
+       if (sk)
+               skb_set_owner_r(skb, sk);
        return sk;
 }
 
@@ -1195,20 +1250,28 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                goto ok;
        }
 
-       if (sk->state == TCP_LISTEN) {
-               struct sock *nsk;
+       /*
+        * We check packets with only the SYN bit set against the
+        * open_request queue too: This increases connection latency a bit,
+        * but is required to detect retransmitted SYNs.
+        *
+        * The ACK/SYN bit check is probably not needed here because
+        * it is checked later again (we play save now).
+        */
+       if (sk->state == TCP_LISTEN && (skb->h.th->ack || skb->h.th->syn)) {
+               struct sock *nsk;
 
-               /* Find possible connection requests. */
-               nsk = tcp_v4_check_req(sk, skb);
-               if (nsk == NULL)
+               /* Find possible connection requests. */
+               nsk = tcp_v4_check_req(sk, skb, &(IPCB(skb)->opt));
+               if (nsk == NULL)
                        goto discard_it;
-
-               release_sock(sk);
-               lock_sock(nsk);
+           
+               release_sock(sk);
+               lock_sock(nsk);
                sk = nsk;
        }
 
-       if (tcp_rcv_state_process(sk, skb, skb->h.th, NULL, skb->len) == 0)
+       if (tcp_rcv_state_process(sk, skb, skb->h.th, &(IPCB(skb)->opt), skb->len) == 0)
                goto ok;
 
 reset:
@@ -1352,7 +1415,6 @@ struct tcp_func ipv4_specific = {
        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,
index 4253c85db790b21b025b6465f4cd44ff5d39d4af..d2b8e00894e5fedc496dce056fe0d22f5fb12e56 100644 (file)
@@ -13,7 +13,7 @@
  * Fixes:
  *             Alan Cox        :       verify_area check.
  *             Alan Cox        :       removed old debugging.
- *
+ *             Andi Kleen      :       add net_ratelimit()  
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -89,3 +89,24 @@ __u32 in_aton(const char *str)
        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; 
+}
index 71ff84b4bb9bbc05fa094204a8001e14f117a317..97833ef59d4769cd6d4bc0bbf068096f314f09a7 100644 (file)
@@ -5,7 +5,7 @@
  *     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
  *
@@ -405,7 +405,23 @@ int icmpv6_rcv(struct sk_buff *skb, struct device *dev,
        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:
index 4bf0207d9ccafeebb37e5fc7983914e659ccc6ba..c2937426459fa2bcb50cee7a9364ad78a4b6a817 100644 (file)
@@ -5,7 +5,7 @@
  *     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
@@ -695,7 +695,7 @@ static struct or_calltable or_ipv6 = {
  * Can some kind of merge be done? -- erics
  */
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
-                              __u32 isn)
+                                                          __u32 isn)
 {
        struct tcp_opt tp;
        struct open_request *req;
@@ -711,6 +711,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
        if (skb->protocol == __constant_htons(ETH_P_IP))
                return tcp_v4_conn_request(sk, skb, ptr, isn);
 
+       if (isn == 0) 
+               isn = tcp_v6_init_sequence(sk,skb);
+
        /*
         *      There are no SYN attacks on IPv6, yet...
         */
@@ -735,7 +738,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
        req->snt_isn = isn;
        tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
        tp.in_mss = 536;
-       tcp_parse_options(skb->h.th,&tp);
+       tcp_parse_options(skb->h.th,&tp,0);
        if (tp.saw_tstamp)
                 req->ts_recent = tp.rcv_tsval;
         req->mss = tp.in_mss;
@@ -778,10 +781,10 @@ static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
 }
 
 static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-                                         struct open_request *req)
+                                         struct open_request *req,
+                                         struct dst_entry *dst)
 {
        struct ipv6_pinfo *np;
-       struct dst_entry *dst;
        struct flowi fl;
        struct tcp_opt *newtp;
        struct sock *newsk;
@@ -791,11 +794,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                 *      v6 mapped
                 */
 
-               newsk = tcp_v4_syn_recv_sock(sk, skb, req);
+               newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
 
-               if (newsk == NULL)
+               if (newsk == NULL) 
                        return NULL;
-
+       
                np = &newsk->net_pinfo.af_inet6;
 
                ipv6_addr_set(&np->daddr, 0, 0, __constant_htonl(0x0000FFFF),
@@ -813,8 +816,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        }
 
        newsk = sk_alloc(GFP_ATOMIC);
-       if (newsk == NULL)
+       if (newsk == NULL) {
+               if (dst)
+                   dst_release(dst);
                return NULL;
+       }
 
        memcpy(newsk, sk, sizeof(*newsk));
 
@@ -902,18 +908,20 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        ipv6_addr_copy(&np->rcv_saddr, &req->af.v6_req.loc_addr);
        np->oif = req->af.v6_req.dev;
 
-       /*
-        *      options / mss / route cache
-        */
-
-       fl.proto = IPPROTO_TCP;
-       fl.nl_u.ip6_u.daddr = &np->daddr;
-       fl.nl_u.ip6_u.saddr = &np->saddr;
-       fl.dev = np->oif;
-       fl.uli_u.ports.dport = newsk->dummy_th.dest;
-       fl.uli_u.ports.sport = newsk->dummy_th.source;
-
-       dst = ip6_route_output(newsk, &fl);
+       if (dst == NULL) {
+           /*
+            *  options / mss / route cache
+            */
+           
+           fl.proto = IPPROTO_TCP;
+           fl.nl_u.ip6_u.daddr = &np->daddr;
+           fl.nl_u.ip6_u.saddr = &np->saddr;
+           fl.dev = np->oif;
+           fl.uli_u.ports.dport = newsk->dummy_th.dest;
+           fl.uli_u.ports.sport = newsk->dummy_th.source;
+           
+           dst = ip6_route_output(newsk, &fl);
+       }
 
        ip6_dst_store(newsk, dst);
 
@@ -1051,7 +1059,7 @@ struct sock *tcp_v6_check_req(struct sock *sk, struct sk_buff *skb)
                        }
 
                        skb_orphan(skb);
-                       sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+                       sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
 
                        tcp_dec_slow_timer(TCP_SLT_SYNACK);
 
@@ -1308,7 +1316,6 @@ static struct tcp_func ipv6_specific = {
        tcp_v6_rebuild_header,
        tcp_v6_conn_request,
        tcp_v6_syn_recv_sock,
-       tcp_v6_init_sequence,
        tcp_v6_get_sock,
        ipv6_setsockopt,
        ipv6_getsockopt,
@@ -1328,7 +1335,6 @@ static struct tcp_func ipv6_mapped = {
        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,
index 1dfdf1832528ae0f60ddc6c2087c3a7c9ed65321..1b95653d5c40b19d6c0fa95cc733bb885273bc92 100644 (file)
@@ -450,7 +450,7 @@ retry:
 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;