summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cvsignore10
-rw-r--r--Documentation/Configure.help2
-rw-r--r--Makefile16
-rw-r--r--arch/mips/Makefile117
-rw-r--r--arch/mips/TODO166
-rw-r--r--arch/mips/acn/Makefile22
-rw-r--r--arch/mips/acn/reset.c12
-rw-r--r--arch/mips/acn/setup.c26
-rw-r--r--arch/mips/boot/.cvsignore1
-rw-r--r--arch/mips/boot/Makefile2
-rw-r--r--arch/mips/boot/compressed/cache.S57
-rw-r--r--arch/mips/boot/compressed/head.S10
-rw-r--r--arch/mips/boot/compressed/misc.c2
-rw-r--r--arch/mips/boot/mkboot.c3
-rw-r--r--arch/mips/config.in157
-rw-r--r--arch/mips/defconfig118
-rw-r--r--arch/mips/deskstation/Makefile2
-rw-r--r--arch/mips/deskstation/hw-access.c20
-rw-r--r--arch/mips/deskstation/int-handler.S4
-rw-r--r--arch/mips/deskstation/reset.c15
-rw-r--r--arch/mips/deskstation/setup.c57
-rw-r--r--arch/mips/doc/mmimpl/openbsd300
-rw-r--r--arch/mips/doc/pagetables.txt87
-rw-r--r--arch/mips/jazz/Makefile2
-rw-r--r--arch/mips/jazz/hw-access.c5
-rw-r--r--arch/mips/jazz/int-handler.S28
-rw-r--r--arch/mips/jazz/jazzdma.c8
-rw-r--r--arch/mips/jazz/reset.c15
-rw-r--r--arch/mips/jazz/setup.c80
-rw-r--r--arch/mips/kernel/.cvsignore1
-rw-r--r--arch/mips/kernel/Makefile41
-rw-r--r--arch/mips/kernel/branch.c2
-rw-r--r--arch/mips/kernel/entry.S180
-rw-r--r--arch/mips/kernel/gdb-low.S21
-rw-r--r--arch/mips/kernel/gdb-stub.c16
-rw-r--r--arch/mips/kernel/head.S1066
-rw-r--r--arch/mips/kernel/ipc.c13
-rw-r--r--arch/mips/kernel/irix5sys.h1024
-rw-r--r--arch/mips/kernel/irixelf.c1374
-rw-r--r--arch/mips/kernel/irixioctl.c254
-rw-r--r--arch/mips/kernel/irixsig.c826
-rw-r--r--arch/mips/kernel/irq.c36
-rw-r--r--arch/mips/kernel/ksyms.c9
-rw-r--r--arch/mips/kernel/process.c138
-rw-r--r--arch/mips/kernel/ptrace.c330
-rw-r--r--arch/mips/kernel/r2300_fpu.S139
-rw-r--r--arch/mips/kernel/r2300_misc.S398
-rw-r--r--arch/mips/kernel/r2300_scall.S86
-rw-r--r--arch/mips/kernel/r2300_switch.S102
-rw-r--r--arch/mips/kernel/r4k_fpu.S148
-rw-r--r--arch/mips/kernel/r4k_misc.S190
-rw-r--r--arch/mips/kernel/r4k_scall.S74
-rw-r--r--arch/mips/kernel/r4k_switch.S71
-rw-r--r--arch/mips/kernel/r6000_fpu.S100
-rw-r--r--arch/mips/kernel/setup.c125
-rw-r--r--arch/mips/kernel/signal.c216
-rw-r--r--arch/mips/kernel/syscall.c213
-rw-r--r--arch/mips/kernel/syscalls.h4
-rw-r--r--arch/mips/kernel/sysirix.c2100
-rw-r--r--arch/mips/kernel/sysmips.c110
-rw-r--r--arch/mips/kernel/tags.c70
-rw-r--r--arch/mips/kernel/traps.c228
-rw-r--r--arch/mips/kernel/unaligned.c14
-rw-r--r--arch/mips/kernel/vm86.c8
-rw-r--r--arch/mips/ld.script.big106
-rw-r--r--arch/mips/ld.script.little (renamed from arch/mips/ld.script)5
-rw-r--r--arch/mips/lib/.cvsignore1
-rw-r--r--arch/mips/lib/Makefile11
-rw-r--r--arch/mips/lib/bcopy.c20
-rw-r--r--arch/mips/lib/bitags.c161
-rw-r--r--arch/mips/lib/byteorder.c13
-rw-r--r--arch/mips/lib/checksum.c180
-rw-r--r--arch/mips/lib/copy_user.S (renamed from arch/mips/mips1/memcpy.S)5
-rw-r--r--arch/mips/lib/dump_tlb.c4
-rw-r--r--arch/mips/lib/memcpy.S222
-rw-r--r--arch/mips/lib/memmove.c39
-rw-r--r--arch/mips/lib/memset.c71
-rw-r--r--arch/mips/lib/pmaxio.S40
-rw-r--r--arch/mips/lib/strlen_user.S2
-rw-r--r--arch/mips/lib/tags.c74
-rw-r--r--arch/mips/lib/tinycon.c4
-rw-r--r--arch/mips/lib/watch.S20
-rw-r--r--arch/mips/man/man8/hardware.839
-rw-r--r--arch/mips/mips1/Makefile28
-rw-r--r--arch/mips/mips1/cache.S162
-rw-r--r--arch/mips/mips1/cpu.c91
-rw-r--r--arch/mips/mips1/fp-context.S159
-rw-r--r--arch/mips/mips1/memset.S27
-rw-r--r--arch/mips/mips1/pagetables.c86
-rw-r--r--arch/mips/mips1/r3000.S1125
-rw-r--r--arch/mips/mips1/showregs.c32
-rw-r--r--arch/mips/mips2/Makefile21
-rw-r--r--arch/mips/mips2/README3
-rw-r--r--arch/mips/mips2/cpu.c91
-rw-r--r--arch/mips/mips2/fp-context.S124
-rw-r--r--arch/mips/mips2/pagetables.c99
-rw-r--r--arch/mips/mips2/showregs.c32
-rw-r--r--arch/mips/mips3/Makefile25
-rw-r--r--arch/mips/mips3/cache.c309
-rw-r--r--arch/mips/mips3/cpu.c96
-rw-r--r--arch/mips/mips3/fp-context.S170
-rw-r--r--arch/mips/mips3/memcpy.S185
-rw-r--r--arch/mips/mips3/memset.c82
-rw-r--r--arch/mips/mips3/pagetables.c297
-rw-r--r--arch/mips/mips3/r4xx0.S841
-rw-r--r--arch/mips/mips3/showregs.c36
-rw-r--r--arch/mips/mips4/Makefile21
-rw-r--r--arch/mips/mips4/README3
-rw-r--r--arch/mips/mips4/cpu.c106
-rw-r--r--arch/mips/mips4/pagetables.c122
-rw-r--r--arch/mips/mm/.cvsignore1
-rw-r--r--arch/mips/mm/Makefile3
-rw-r--r--arch/mips/mm/andes.c102
-rw-r--r--arch/mips/mm/fault.c30
-rw-r--r--arch/mips/mm/init.c95
-rw-r--r--arch/mips/mm/loadmmu.c105
-rw-r--r--arch/mips/mm/r2300.c271
-rw-r--r--arch/mips/mm/r4xx0.c2456
-rw-r--r--arch/mips/mm/r6000.c182
-rw-r--r--arch/mips/mm/stack.c26
-rw-r--r--arch/mips/mm/tfp.c103
-rw-r--r--arch/mips/sgi/kernel/.cvsignore1
-rw-r--r--arch/mips/sgi/kernel/Makefile30
-rw-r--r--arch/mips/sgi/kernel/indyIRQ.S138
-rw-r--r--arch/mips/sgi/kernel/indy_hpc.c114
-rw-r--r--arch/mips/sgi/kernel/indy_int.c579
-rw-r--r--arch/mips/sgi/kernel/indy_mc.c153
-rw-r--r--arch/mips/sgi/kernel/indy_timer.c298
-rw-r--r--arch/mips/sgi/kernel/reset.c14
-rw-r--r--arch/mips/sgi/kernel/setup.c83
-rw-r--r--arch/mips/sgi/kernel/system.c168
-rw-r--r--arch/mips/sgi/kernel/time.c14
-rw-r--r--arch/mips/sgi/prom/.cvsignore1
-rw-r--r--arch/mips/sgi/prom/Makefile23
-rw-r--r--arch/mips/sgi/prom/cmdline.c60
-rw-r--r--arch/mips/sgi/prom/console.c24
-rw-r--r--arch/mips/sgi/prom/env.c20
-rw-r--r--arch/mips/sgi/prom/file.c58
-rw-r--r--arch/mips/sgi/prom/init.c59
-rw-r--r--arch/mips/sgi/prom/memory.c129
-rw-r--r--arch/mips/sgi/prom/misc.c109
-rw-r--r--arch/mips/sgi/prom/printf.c34
-rw-r--r--arch/mips/sgi/prom/salone.c24
-rw-r--r--arch/mips/sgi/prom/tags.c67
-rw-r--r--arch/mips/sgi/prom/time.c17
-rw-r--r--arch/mips/sgi/prom/tree.c107
-rw-r--r--arch/mips/sni/Makefile6
-rw-r--r--arch/mips/sni/bios32.c264
-rw-r--r--arch/mips/sni/hw-access.c6
-rw-r--r--arch/mips/sni/int-handler.S37
-rw-r--r--arch/mips/sni/setup.c3
-rw-r--r--arch/mips/tools/Makefile26
-rw-r--r--arch/mips/tools/offset.c128
-rw-r--r--arch/mips/tools/offset.h89
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/block/.cvsignore1
-rw-r--r--drivers/block/floppy.c29
-rw-r--r--drivers/block/genhd.c88
-rw-r--r--drivers/block/ll_rw_blk.c4
-rw-r--r--drivers/block/rd.c3
-rw-r--r--drivers/cdrom/.cvsignore1
-rw-r--r--drivers/char/.cvsignore3
-rw-r--r--drivers/char/Makefile8
-rw-r--r--drivers/char/console.c31
-rw-r--r--drivers/char/ftape/.cvsignore1
-rw-r--r--drivers/char/keyboard.c16
-rw-r--r--drivers/char/lp.c58
-rw-r--r--drivers/char/psaux.c151
-rw-r--r--drivers/char/selection.h35
-rw-r--r--drivers/char/softdog.c2
-rw-r--r--drivers/char/vesa_blank.c11
-rw-r--r--drivers/char/vga.c32
-rw-r--r--drivers/char/vt.c5
-rw-r--r--drivers/isdn/.cvsignore1
-rw-r--r--drivers/isdn/icn/.cvsignore1
-rw-r--r--drivers/isdn/pcbit/.cvsignore1
-rw-r--r--drivers/isdn/teles/.cvsignore1
-rw-r--r--drivers/isdn/teles/buffers.c5
-rw-r--r--drivers/isdn/teles/callc.c5
-rw-r--r--drivers/net/.cvsignore1
-rw-r--r--drivers/net/Config.in6
-rw-r--r--drivers/net/Makefile4
-rw-r--r--drivers/net/Space.c8
-rw-r--r--drivers/net/lance32.c7
-rw-r--r--drivers/net/sgiseeq.c737
-rw-r--r--drivers/net/sgiseeq.h103
-rw-r--r--drivers/net/sonic.c6
-rw-r--r--drivers/pci/.cvsignore1
-rw-r--r--drivers/sbus/.cvsignore1
-rw-r--r--drivers/sbus/char/.cvsignore1
-rw-r--r--drivers/scsi/.cvsignore1
-rw-r--r--drivers/scsi/Makefile8
-rw-r--r--drivers/scsi/hosts.c9
-rw-r--r--drivers/scsi/scsi.c6
-rw-r--r--drivers/scsi/scsicam.c5
-rw-r--r--drivers/scsi/seagate.c64
-rw-r--r--drivers/scsi/sgiwd93.c246
-rw-r--r--drivers/scsi/sgiwd93.h52
-rw-r--r--drivers/scsi/wd33c93.c2962
-rw-r--r--drivers/scsi/wd33c93.h371
-rw-r--r--drivers/sgi/Makefile22
-rw-r--r--drivers/sgi/char/.cvsignore1
-rw-r--r--drivers/sgi/char/Makefile17
-rw-r--r--drivers/sgi/char/linux_logo.h909
-rw-r--r--drivers/sgi/char/newport.c940
-rw-r--r--drivers/sgi/char/newport.h409
-rw-r--r--drivers/sgi/char/sgicons.c28
-rw-r--r--drivers/sgi/char/sgiserial.c2014
-rw-r--r--drivers/sgi/char/sgiserial.h444
-rw-r--r--drivers/sound/.cvsignore1
-rw-r--r--fs/.cvsignore1
-rw-r--r--fs/affs/.cvsignore1
-rw-r--r--fs/binfmt_elf.c81
-rw-r--r--fs/exec.c11
-rw-r--r--fs/ext/.cvsignore1
-rw-r--r--fs/ext2/.cvsignore1
-rw-r--r--fs/fat/.cvsignore1
-rw-r--r--fs/fat/inode.c8
-rw-r--r--fs/hpfs/.cvsignore1
-rw-r--r--fs/inode.c3
-rw-r--r--fs/isofs/.cvsignore1
-rw-r--r--fs/minix/.cvsignore1
-rw-r--r--fs/msdos/.cvsignore1
-rw-r--r--fs/namei.c9
-rw-r--r--fs/ncpfs/.cvsignore1
-rw-r--r--fs/nfs/.cvsignore1
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfs/nfsroot.c1
-rw-r--r--fs/nfs/sock.c8
-rw-r--r--fs/proc/.cvsignore1
-rw-r--r--fs/proc/array.c19
-rw-r--r--fs/smbfs/.cvsignore1
-rw-r--r--fs/sysv/.cvsignore1
-rw-r--r--fs/ufs/.cvsignore1
-rw-r--r--fs/umsdos/.cvsignore1
-rw-r--r--fs/vfat/.cvsignore1
-rw-r--r--fs/xiafs/.cvsignore1
-rw-r--r--include/asm-alpha/floppy.h2
-rw-r--r--include/asm-alpha/keyboard.h2
-rw-r--r--include/asm-alpha/mc146818rtc.h23
-rw-r--r--include/asm-alpha/page.h2
-rw-r--r--include/asm-alpha/system.h5
-rw-r--r--include/asm-generic/bitops.h53
-rw-r--r--include/asm-i386/keyboard.h2
-rw-r--r--include/asm-i386/mc146818rtc.h23
-rw-r--r--include/asm-i386/page.h14
-rw-r--r--include/asm-i386/slots.h17
-rw-r--r--include/asm-i386/system.h5
-rw-r--r--include/asm-m68k/system.h5
-rw-r--r--include/asm-mips/asm.h19
-rw-r--r--include/asm-mips/asmmacro.h115
-rw-r--r--include/asm-mips/bitops.h223
-rw-r--r--include/asm-mips/bootinfo.h84
-rw-r--r--include/asm-mips/branch.h2
-rw-r--r--include/asm-mips/byteorder.h2
-rw-r--r--include/asm-mips/cacheops.h (renamed from include/asm-mips/cache.h)30
-rw-r--r--include/asm-mips/checksum.h19
-rw-r--r--include/asm-mips/cpu.h36
-rw-r--r--include/asm-mips/dec/decstation.h54
-rw-r--r--include/asm-mips/dec/kn02.h52
-rw-r--r--include/asm-mips/dec/maxine.h52
-rw-r--r--include/asm-mips/deskstation.h15
-rw-r--r--include/asm-mips/dma.h7
-rw-r--r--include/asm-mips/elf.h34
-rw-r--r--include/asm-mips/errno.h7
-rw-r--r--include/asm-mips/irq.h2
-rw-r--r--include/asm-mips/jazz.h6
-rw-r--r--include/asm-mips/keyboard.h40
-rw-r--r--include/asm-mips/mipsconfig.h31
-rw-r--r--include/asm-mips/mipsregs.h91
-rw-r--r--include/asm-mips/mmu_context.h37
-rw-r--r--include/asm-mips/offset.h89
-rw-r--r--include/asm-mips/page.h42
-rw-r--r--include/asm-mips/pgtable.h693
-rw-r--r--include/asm-mips/pica.h181
-rw-r--r--include/asm-mips/processor.h118
-rw-r--r--include/asm-mips/ptrace.h87
-rw-r--r--include/asm-mips/r4kcache.h1025
-rw-r--r--include/asm-mips/reg.h95
-rw-r--r--include/asm-mips/register.h34
-rw-r--r--include/asm-mips/segment.h6
-rw-r--r--include/asm-mips/sgi.h42
-rw-r--r--include/asm-mips/sgialib.h118
-rw-r--r--include/asm-mips/sgiarcs.h351
-rw-r--r--include/asm-mips/sgihpc.h340
-rw-r--r--include/asm-mips/sgimc.h223
-rw-r--r--include/asm-mips/sgint23.h179
-rw-r--r--include/asm-mips/shmparam.h2
-rw-r--r--include/asm-mips/sigcontext.h1
-rw-r--r--include/asm-mips/slots.h23
-rw-r--r--include/asm-mips/sni.h15
-rw-r--r--include/asm-mips/stackframe.h437
-rw-r--r--include/asm-mips/string.h333
-rw-r--r--include/asm-mips/system.h58
-rw-r--r--include/asm-mips/termbits.h26
-rw-r--r--include/asm-mips/termios.h5
-rw-r--r--include/asm-mips/uaccess.h6
-rw-r--r--include/asm-mips/unaligned.h113
-rw-r--r--include/asm-mips/unistd.h7
-rw-r--r--include/asm-mips/user.h6
-rw-r--r--include/asm-mips/vector.h2
-rw-r--r--include/asm-ppc/system.h5
-rw-r--r--include/asm-sparc/page.h2
-rw-r--r--include/asm-sparc/system.h5
-rw-r--r--include/linux/.cvsignore3
-rw-r--r--include/linux/binfmts.h1
-rw-r--r--include/linux/elf.h12
-rw-r--r--include/linux/fs.h11
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/ipc.h4
-rw-r--r--include/linux/mm.h14
-rw-r--r--include/linux/msg.h4
-rw-r--r--include/linux/mtio.h4
-rw-r--r--include/linux/personality.h3
-rw-r--r--include/linux/proc_fs.h1
-rw-r--r--include/linux/string.h4
-rw-r--r--include/linux/tcp.h2
-rw-r--r--include/linux/time.h4
-rw-r--r--include/linux/tty.h2
-rw-r--r--init/main.c49
-rw-r--r--ipc/.cvsignore1
-rw-r--r--kernel/.cvsignore1
-rw-r--r--kernel/exit.c12
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/ksyms.c2
-rw-r--r--kernel/panic.c20
-rw-r--r--kernel/sched.c11
-rw-r--r--kernel/sys.c1
-rw-r--r--lib/.cvsignore1
-rw-r--r--lib/vsprintf.c25
-rw-r--r--log19
-rw-r--r--mm/.cvsignore1
-rw-r--r--mm/kmalloc.c98
-rw-r--r--mm/mmap.c2
-rw-r--r--net/.cvsignore1
-rw-r--r--net/802/.cvsignore1
-rw-r--r--net/appletalk/.cvsignore1
-rw-r--r--net/ax25/.cvsignore1
-rw-r--r--net/bridge/.cvsignore1
-rw-r--r--net/core/.cvsignore1
-rw-r--r--net/ethernet/.cvsignore1
-rw-r--r--net/ipv4/.cvsignore1
-rw-r--r--net/ipx/.cvsignore1
-rw-r--r--net/netrom/.cvsignore1
-rw-r--r--net/unix/.cvsignore1
345 files changed, 27635 insertions, 11236 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 000000000..8a3312ba7
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,10 @@
+!core
+.config
+.depend
+.hdepend
+.version
+System.map
+vmlinux
+modules
+nohup.out
+
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index cc97ae57d..2804e321e 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -382,7 +382,7 @@ CONFIG_ACER_PICA_61
lynx, netscape or Mosaic).
Support for DECstation
-CONFIG_MIPS_DECSTATION
+CONFIG_DECSTATION
The DECStation 3100 (with a MIPS R2000 series CPU) and DECStation
5000/xxx (MIPS R3000 series CPU) are also sometimes labeled
PMAX. They often run the Ultrix operating system. To compile a Linux
diff --git a/Makefile b/Makefile
index 25fe85fd3..0a255cb8f 100644
--- a/Makefile
+++ b/Makefile
@@ -24,23 +24,21 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
HPATH = $(TOPDIR)/include
-FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net
-HOSTCC =gcc
-HOSTCFLAGS =-O2 -fomit-frame-pointer
+HOSTCC = gcc
+HOSTCFLAGS = -O2 -fomit-frame-pointer
CROSS_COMPILE =
AS =$(CROSS_COMPILE)as
LD =$(CROSS_COMPILE)ld
CC =$(CROSS_COMPILE)gcc -D__KERNEL__ -I$(HPATH)
-CPP =$(CC) -E $(CFLAGS)
+CPP =$(CC) -E
AR =$(CROSS_COMPILE)ar
NM =$(CROSS_COMPILE)nm
STRIP =$(CROSS_COMPILE)strip
-RANLIB =$(CROSS_COMPILE)ranlib
OBJCOPY =$(CROSS_COMPILE)objcopy
-OBJDUMP =$(CROSS_COMPILE)objdump
+OBJDUMP =$(CROSS_COMPILE)objdump
MAKE =make
all: do-it-all
@@ -149,6 +147,10 @@ ifdef CONFIG_SBUS
DRIVERS := $(DRIVERS) drivers/sbus/sbus.a
endif
+ifdef CONFIG_SGI
+DRIVERS := $(DRIVERS) drivers/sgi/sgi.a
+endif
+
include arch/$(ARCH)/Makefile
ifdef SMP
@@ -179,7 +181,7 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(FILESYSTEMS) \
$(DRIVERS) \
$(LIBS) -o vmlinux
- $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\(\$$\)' | sort > System.map
+ $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map
symlinks:
rm -f include/asm
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index c7ba5db9b..19a632ebb 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -12,19 +12,17 @@
#
# Copyright (C) 1994, 1995, 1996 by Ralf Baechle
# DECStation modifications by Paul M. Antoine, 1996
-# ACN MIPS board modifications by Robin Farine (Robin.Farine@info.unine.ch)
-# and Didier Frick (dfrick@dial.eunet.ch), copyright (C) 1996 by ACN S.A.
#
ifdef CONFIG_CPU_LITTLE_ENDIAN
-cross-target = mipsel-linux-
+CROSS_COMPILE = mipsel-
ifdef CONFIG_MIPS_ECOFF
oformat = ecoff-littlemips
else
-oformat = a.out-mips-little-linux
+oformat = a.out-mips-big-linux
endif
else
-cross-target = mips-linux-
+CROSS_COMPILE = mips-
ifdef CONFIG_MIPS_ECOFF
oformat = ecoff-bigmips
else
@@ -32,65 +30,37 @@ oformat = a.out-mips-big-linux
endif
endif
-ifdef CONFIG_CROSS_COMPILE
-CROSS_COMPILE := $(cross-target)
+ifdef CONFIG_EXTRA_ELF_COMPILER
+CROSS_COMPILE := $(CROSS_COMPILE)linuxelf-
else
-CROSS_COMPILE :=
+CROSS_COMPILE := $(CROSS_COMPILE)linux-
endif
-LINKFLAGS = -N
+LINKFLAGS = -static -N
#
-# The GCC uses -G 0 -mabicalls -fpic as default. We don't need PIC
+# The new ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC
# code in the kernel since it only slows down the whole thing. For the
# old GCC these options are just the defaults. At some point we might
# make use of global pointer optimizations.
#
-# We also pass -G 0 to the linker to avoid generation of a .scommon section.
-#
# The DECStation requires an ECOFF kernel for remote booting, other MIPS
-# machines may also. We build an ELF kernel and them convert it into an
-# ECOFF kernel.
+# machines may also.
#
+ifdef CONFIG_ELF_KERNEL
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
-SUBDIRS += arch/mips/mips1
-cpu-core = arch/mips/mips1/mips.o
-endif
-ifdef CONFIG_CPU_R6000
-CFLAGS := $(CFLAGS) -mcpu=r6000 -mips2
-SUBDIRS += arch/mips/mips2
-cpu-core = arch/mips/mips2/mips.o
-endif
-ifdef CONFIG_CPU_R4X00
-ifdef CONFIG_OPTIMIZE_R4600
-CFLAGS := $(CFLAGS) -mcpu=r4600 -mips3
-else
-CFLAGS := $(CFLAGS) -mcpu=r4400 -mips3
-endif
-SUBDIRS += arch/mips/mips3
-cpu-core = arch/mips/mips3/mips.o
-endif
-ifdef CONFIG_CPU_R8000
-CFLAGS := $(CFLAGS) -mcpu=r8000 -mips4
-SUBDIRS += arch/mips/mips3
-cpu-core = arch/mips/mips3/mips.o
-endif
-ifdef CONFIG_CPU_R10000
-CFLAGS := $(CFLAGS) -mcpu=r8000 -mips4
-SUBDIRS += arch/mips/mips3
-cpu-core = arch/mips/mips3/mips.o
-endif
+CFLAGS := $(CFLAGS) -mips2
#
# Board dependand options and extra files
@@ -98,78 +68,72 @@ endif
ifdef CONFIG_ACER_PICA_61
ARCHIVES += arch/mips/jazz/jazz.o
SUBDIRS += arch/mips/jazz
-LINKSCRIPT += arch/mips/ld.script
LOADADDR += 0x80000000
endif
-ifdef CONFIG_ACN_MIPS_BOARD
-ARCHIVES += arch/mips/acn/acn.o
-SUBDIRS += arch/mips/acn
-LINKSCRIPT += arch/mips/ld.script
-LOADADDR += 0x80000000
-endif
-ifdef CONFIG_MIPS_DECSTATION
+ifdef CONFIG_DECSTATION
ARCHIVES += arch/mips/dec/dec.o
SUBDIRS += arch/mips/dec
-LINKSCRIPT += arch/mips/ld.script
+LINKSCRIPT += arch/mips/dec/ld.script
LOADADDR += 0x80000000
endif
ifdef CONFIG_DESKSTATION_RPC44
ARCHIVES += arch/mips/deskstation/deskstation.o
SUBDIRS += arch/mips/deskstation
-LINKSCRIPT += arch/mips/ld.script
-LOADADDR += 0x80000000
+LOADADDR += 0x80100000
endif
ifdef CONFIG_DESKSTATION_TYNE
ARCHIVES += arch/mips/deskstation/deskstation.o
SUBDIRS += arch/mips/deskstation
-LINKSCRIPT += arch/mips/ld.script
LOADADDR += 0x80000000
endif
ifdef CONFIG_MIPS_MAGNUM_3000
-LINKFLAGS += -Ttext 0x80100000
-endif
-ifdef CONFIG_MIPS_MAGNUM_4000
-ARCHIVES += arch/mips/jazz/jazz.o
-SUBDIRS += arch/mips/jazz
-LINKSCRIPT += arch/mips/ld.script
LOADADDR += 0x80000000
endif
-ifdef CONFIG_OLIVETTI_M700
+ifdef CONFIG_MIPS_MAGNUM_4000
ARCHIVES += arch/mips/jazz/jazz.o
SUBDIRS += arch/mips/jazz
-LINKSCRIPT += arch/mips/ld.script
LOADADDR += 0x80000000
endif
ifdef CONFIG_SNI_RM200_PCI
ARCHIVES += arch/mips/sni/sni.o
SUBDIRS += arch/mips/sni
-LINKSCRIPT += arch/mips/ld.script
LOADADDR += 0x80000000
endif
+ifdef CONFIG_SGI
+ARCHIVES += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a
+SUBDIRS += arch/mips/sgi/kernel arch/mips/sgi/prom
+LOADADDR += 0x88069000
+HOSTCC = cc
+endif
#
# Choosing incompatible machines durings configuration will result in
-# error messages during linking
+# error messages during linking. Select a default linkscript if
+# none has been choosen above.
#
-ifdef LINKSCRIPT
-LINKFLAGS += -T $(word 1,$(LINKSCRIPT))
+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))
ifdef LOADADDR
LINKFLAGS += -Ttext $(word 1,$(LOADADDR))
endif
#
-# The pipe options is bad for low-mem machines
-# Uncomment this if you want this. Helps most on diskless
-# Linux machines.
+# The pipe options is bad for my low-mem machine
+# Uncomment this if you want this.
#
-CFLAGS += #-pipe
+#CFLAGS += -pipe
HEAD := arch/mips/kernel/head.o
-SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib
-ARCHIVES := $(cpu-core) arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
+SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools)
+ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
@@ -185,6 +149,7 @@ zdisk: vmlinux
archclean:
@$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
+ $(MAKE) -C arch/$(ARCH)/tools clean
archdep:
@$(MAKEBOOT) dep
diff --git a/arch/mips/TODO b/arch/mips/TODO
deleted file mode 100644
index c5df56d0c..000000000
--- a/arch/mips/TODO
+++ /dev/null
@@ -1,166 +0,0 @@
- - Kernel:
- - fd_set_dma_addr() Virtuelle Adressen -> Bus adressen
- - __pa() und __va() Makro Benutzer in include/asm-mips/ aendern
- - The PICs in some RISC PC class machines are cascaded, in others not.
- Yuck. If they're using PC crap part they should do it right ...
- - Print a warning for R4600 V1.0 users; there is a problem with the
- caches that isn't handled yet in the kernel.
- - IP checksums overhaul. (Dave said he did for the SGI port)
- - The networking related constants still aren't indentical with IRIX/ABI.
- - Check the definitions for F_EXLCK and F_SHLCK in include/asm-mips/fcntl.h
- for correctness and compatibility with MIPS ABI.
- - Check the definitions for O_NDELAY in include/asm-mips/fcntl.h for
- correctness and compatibility with MIPS ABI.
- - What are the fields l_sysid and pad in struct flock supposed to contain?
- Do we need to handle them in the kernel?
- - Check the resource limits defines in asm-mips/resource.h
- - Recheck struct stat in asm-mips/stat.h
- - Use timestruc_t in struct stat in asm/stat.h instead of time_t
- - asm-mips/termios.h is pretty hacked; it should be verified for ABI
- conformance by someone who has the documentation.
- - Cleanup include files. To many files include too many others.
- - Fix asm-mips/elf.h. This is just good enough to make the thing compile.
- - asm-mips/socket.h needs further fixes for ABI conformance.
- - linux/types.h / asm-mips/types.h: FD_SETSIZE should be 1024, not 256.
- 1024 is required by the ABI.
- - asm-mips/socket.h: check the FIO* and SIO* defines.
- - linux/sockios.h: The sockios aren't ABI compatible.
- - For performance reasons the missing inline functions in asm-mips/string.h
- should be implemented.
- - For performance reasons the tlbflush code should be rewritten.
- - Module support for the Sonic driver.
- - From 1.3.17 on the kernel does no more compile with network support but
- without procfs support included.
- - /proc/cpuinfo should contain more information that just CPU model,
- computer model and damn BogoMIPS.
- - The sysmips(2) syscall needs to be tested. Some of the subcommands
- are still missing.
- - The whole kernel is junked with #if 0 ... #endif debug code. Cleanup.
- - Use set_pte hook in page.h. It's the more effective and elegant way
- than my solution which was just optimized just to better survives other
- peoples kernel patches without rejects ...
- - Build the machine vector in arch/mips/kernel/setup.c table using
- constructors, not static initialization.
- - Can the virtual address spaces of the kernel virtual memory and page
- tables colide with each other? (Yes, when the kernel uses excessive
- amounts of kernel virtual memory.)
- - Test the memory protection with nuclear warheads model W-crashme ...
- - die_if_kernel() should try to handle branch delay slots.
- - Try to reduce dependencies between header files.
- - Unroll some of the memset type assembler loops.
- - Replace memcpy and friends by a highly optimized routine. Will probably
- speed up scrolling by another 100 %. Certainly not required by the Acer,
- but Magnum and Olivetti ...
- - Hmm... Think that the i386 version of the kernel has a bug. It doesn't
- set the carry flag for syscalls > NR_syscalls. Really unimportant.
- - The size_t definitions in <linux/stddef.h> and <asm/types.h> are
- incompatible.
- - Cleanup the parameter passing to new execve-ed ELF/a.out executables.
- - Cleanup drivers/char/keyboard.c and send it to Linus.
- - No SMP support yet.
- - Caches:
- - sys_cacheflush should check for illegal flags
- - The way cache flushing is being done in floppy.c is dangerous because
- the flushing is actually a writeback invalidate. Could corrupt data.
- - The kernel is very conservative about flushing the TLB/caches. Try
- to eleminate flushing as far as possible.
- - page colouring NEEDS to be implemented for R4000+ to circument the
- page aliasing problem due to the stupid R4000 cache. There are
- alternatives but they'd be dog slow.
- - Allocate the swapper pgd dynamically.
- - it is impossible to send signals >= 32 (send_sig() in kernel/exit.c)
- - Which is the unit of RLIMIT_CPU?
- - Eleminate invalid_pte_table. It contains only zeros just like
- empty_zero_page.
- - Writing to floppies doesn't work in 1.3.62.
- - Cleanup the arch/mips/ directory structure. Split up kernel/ and mm/
- in cpu dependand and machine dependand directories. Do this also for
- the configfile.
- - FIXME: resume() assumes current == prev.
- - The timer interrupt runs with interrupts disabled. This means that
- sometimes interrupts are off for a long time. Use some other strategy
- for the jiffies stuff.
- - Scrollback in the VGA console is broken.
- - Modify pte_alloc() the same way as for Intel.
- - Binutils 2.7:
- - 2.6 introduces a new machine instruction waiti for the 4010. Is this
- the same machine instruction as wait for R4200/R4300i/R4600? At least
- the opcodes are the sames.
- - strip --remove-section= with no other options also removes the symbols.
- - Shouldn't the binutils support an ulwu macro?
- - uld, ulw generate bad code for the special case when both registers are
- the same.
- - MIPS support in gprof is missing.
- - When explicitly giving an nonexistant entry point as -e <entry> point
- during loading a shared lib, ld should complain.
- - The assembler dies when the argument to .gpword is a extern symbol.
- - This source breaks GAS in binutils 2.7:
- .macro ins
- .if (3 | 16)
- .endif
- .endm
-
- ins
- - GNU libc 951215:
- - There are lots of collisions between structures in the kernel header
- files and the includes generated by the kernel.
- - setjmp & friends fail for the 32 double register model of > MIPS3.
- - R4400:
- - Per once told me he found something he believes is a CPU bug. Ask him if
- it's really a bug.
- - R8000 in arch/mips/config.in:
- - Can the R8000 do a TLB shutdown like the R4000 or is it like the R10000?
- - Manpages:
- - The sysmips(2) documentation needs to be completed.
- - The cacheflush(2) and cachectl(2) documentation needs to be proof read
- by a native speaker.
- - Translate the manpages into as many foreign languages as possible.
- - Send the corrected/translated manpages to the LDP/Andries Brouwer.
- - GCC 2.7.2:
- - The info files lack descriptions of some MIPS options like -mips4.
- - The multilib support has no way to specify incompatible options
- like -mabicalls and -fno-PIC. For such option pairs library compilation
- is nonsense and breaks anyway.
- - The following macros work but generate good code only for certain
- data types. We only use get_unaligned() for accessing unaligned ints
- and then GCC makes full score anyway ...
-
-#define get_unaligned(ptr) \
- ({ \
- struct __unal { \
- __typeof__(*(ptr)) __x __attribute__((packed)); \
- }; \
- \
- ((struct __unal *)(ptr))->__x; \
- })
-
-#define put_unaligned(ptr,val) \
- ({ \
- struct __unal { \
- __typeof__(*(ptr)) __x __attribute__((packed)); \
- }; \
- \
- ((struct __unal *)(ptr))->__x = (val); \
- })
-
-int
-foo(int *p)
-{
- return get_unaligned(p);
-}
-
-int
-bar(int *p, int var)
-{
- put_unaligned(p, var);
-}
-
-struct blah {
- char x1 __attribute__((packed));
- int x2 __attribute__((packed));
-};
-
-fasel(struct blah *p, int var)
-{
- p->x2 = var;
-}
diff --git a/arch/mips/acn/Makefile b/arch/mips/acn/Makefile
deleted file mode 100644
index 3821d7b62..000000000
--- a/arch/mips/acn/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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 reset.o setup.o
-
-int-handler.o: int-handler.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/acn/reset.c b/arch/mips/acn/reset.c
deleted file mode 100644
index 149fedd9d..000000000
--- a/arch/mips/acn/reset.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * linux/arch/mips/sni/process.c
- *
- * Reset the ACN board.
- */
-#include <asm/io.h>
-#include <asm/system.h>
-
-void
-acn_hard_reset_now(void)
-{
-}
diff --git a/arch/mips/acn/setup.c b/arch/mips/acn/setup.c
deleted file mode 100644
index 5fe8731e5..000000000
--- a/arch/mips/acn/setup.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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/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/vector.h>
-
-extern void acn_hard_reset_now(void);
-
-void
-sni_rm200_pci_setup(void)
-{
- hard_reset_now = acn_hard_reset_now;
-}
diff --git a/arch/mips/boot/.cvsignore b/arch/mips/boot/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/boot/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index 3a8698d34..fd445c865 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -34,7 +34,7 @@ mkboot: mkboot.c
$(HOSTCC) -o $@ $^
zdisk: zImage
- mcopy -n zImage a:vmlinux
+ mcopy -o zImage a:vmlinux
dep:
$(CPP) -M *.[cS] > .depend
diff --git a/arch/mips/boot/compressed/cache.S b/arch/mips/boot/compressed/cache.S
index 3e6a3d57d..7cc97b53e 100644
--- a/arch/mips/boot/compressed/cache.S
+++ b/arch/mips/boot/compressed/cache.S
@@ -18,10 +18,7 @@
#include <asm/asm.h>
#include <asm/cachectl.h>
#include <asm/mipsregs.h>
-#include <asm/uaccess.h>
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
+#include <asm/segment.h>
/*
* Some bits in the config register
@@ -29,8 +26,6 @@
#define CONFIG_IB (1<<5)
#define CONFIG_DB (1<<4)
-#define CACHEBLOCKS 32
-
/*
* Flush instruction/data caches
*
@@ -45,14 +40,16 @@
.set noreorder
LEAF(cacheflush)
andi t1,a2,DCACHE
+
beqz t1,do_icache
- li t0,KSEG0 # delay slot
+ li t0,KSEG0
/*
* Writeback data cache, even lines
*/
- li t1,CACHEBLOCKS-1
-1: cache Index_Writeback_Inv_D,0(t0)
+ 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)
@@ -69,8 +66,9 @@
cache Index_Writeback_Inv_D,448(t0)
cache Index_Writeback_Inv_D,480(t0)
addiu t0,512
+
bnez t1,1b
- subu t1,1
+ subu t1,1
/*
* Writeback data cache, odd lines
@@ -79,8 +77,9 @@
mfc0 t1,CP0_CONFIG
andi t1,CONFIG_IB
bnez t1,do_icache
- li t1,CACHEBLOCKS-1
-1: cache Index_Writeback_Inv_D,16(t0)
+ 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)
@@ -97,18 +96,21 @@
cache Index_Writeback_Inv_D,464(t0)
cache Index_Writeback_Inv_D,496(t0)
addiu t0,512
+
bnez t1,1b
- subu t1,1
+ subu t1,1
-do_icache: andi t1,a2,ICACHE
+do_icache:
+ andi t1,a2,ICACHE
beqz t1,done
+ lui t0,0x8000
/*
* Flush instruction cache, even lines
*/
- lui t0,0x8000
- li t1,CACHEBLOCKS-1
-1: cache Index_Invalidate_I,0(t0)
+ 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)
@@ -125,8 +127,9 @@ do_icache: andi t1,a2,ICACHE
cache Index_Invalidate_I,448(t0)
cache Index_Invalidate_I,480(t0)
addiu t0,512
+
bnez t1,1b
- subu t1,1
+ subu t1,1
/*
* Flush instruction cache, even lines
@@ -135,8 +138,10 @@ do_icache: andi t1,a2,ICACHE
mfc0 t1,CP0_CONFIG
andi t1,CONFIG_DB
bnez t1,done
- li t1,CACHEBLOCKS-1
-1: cache Index_Invalidate_I,16(t0)
+ 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)
@@ -153,13 +158,11 @@ do_icache: andi t1,a2,ICACHE
cache Index_Invalidate_I,464(t0)
cache Index_Invalidate_I,496(t0)
addiu t0,512
+
bnez t1,1b
- subu t1,1
+ subu t1,1
-done: j ra
- nop
+done:
+ j ra
+ nop
END(sys_cacheflush)
-
-#else
-#error "No R3000 cacheflushing implemented yet!"
-#endif
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
index 0ca599563..dad90855e 100644
--- a/arch/mips/boot/compressed/head.S
+++ b/arch/mips/boot/compressed/head.S
@@ -28,16 +28,18 @@
la t0,_edata
la t1,_end
sw zero,(t0)
-1: addiu t0,4
+1:
+ addiu t0,4
+
bnel t0,t1,1b
- sw zero,(t0)
+ sw zero,(t0)
END(kernel_entry)
/*
* Do the decompression, and jump to the new kernel..
*/
jal C_LABEL(decompress_kernel)
- nop
+ nop
/*
* Flush caches
@@ -49,4 +51,4 @@
*/
la t0,KSEG0
jr t0
- nop
+ nop
diff --git a/arch/mips/boot/compressed/misc.c b/arch/mips/boot/compressed/misc.c
index 625a75cd0..1e3bb5f82 100644
--- a/arch/mips/boot/compressed/misc.c
+++ b/arch/mips/boot/compressed/misc.c
@@ -12,7 +12,7 @@
#include "gzip.h"
#include "lzw.h"
-#include <asm/uaccess.h>
+#include <asm/segment.h>
/*
* These are set up by the setup-routine at boot-time:
diff --git a/arch/mips/boot/mkboot.c b/arch/mips/boot/mkboot.c
index c34332f99..48f27113e 100644
--- a/arch/mips/boot/mkboot.c
+++ b/arch/mips/boot/mkboot.c
@@ -381,7 +381,7 @@ main(argc, argv)
fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n");
exit(1);
}
-
+
if (argc != 3)
usage(argv[0]);
@@ -597,7 +597,6 @@ main(argc, argv)
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 + 16, 0); /* 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 */
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 3dd4c00c0..e2065779e 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -11,24 +11,17 @@ endmenu
mainmenu_option next_comment
comment 'Machine selection'
-
bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Support for ACN MIPS Board' CONFIG_ACN_MIPS_BOARD
-fi
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Support for DECstation' CONFIG_MIPS_DECSTATION
-fi
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ 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-10' CONFIG_OLIVETTI_M700
-if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
- "$CONFIG_OLIVETTI_M700" = "y" ]; then
- define_bool CONFIG_VIDEO_G364 y
+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 \
@@ -40,57 +33,23 @@ if [ "$CONFIG_ACER_PICA_61" = "y" -o \
"$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then
define_bool CONFIG_MIPS_JAZZ y
fi
-if [ "$CONFIG_ACN_MIPS_BOARD" = "y" ]; then
- define_bool CONFIG_SERIAL_ONLY_CONSOLE y
- define_bool CONFIG_NO_SWAPPER y
- define_bool CONFIG_CUSTOM_UART y
- define_bool CONFIG_CUSTOM_TIMER y
-fi
-endmenu
-
-mainmenu_option next_comment
-comment 'CPU selection'
-
-choice 'CPU type' \
- "R3000 CONFIG_CPU_R3000 \
- R6000 CONFIG_CPU_R6000 \
- R4x00 CONFIG_CPU_R4X00 \
- 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_R8000" = "y" ]; then
- define_bool CONFIG_TLB_SHUTDOWN y
-fi
-if [ "$CONFIG_CPU_R4X00" = "y" ]; then
- bool "Optimize for R4600 only" CONFIG_OPTIMIZE_R4600
-fi
endmenu
mainmenu_option next_comment
comment 'General setup'
-define_bool CONFIG_BINFMT_ELF y
-define_bool CONFIG_BINFMT_AOUT n
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
-fi
-if [ "$CONFIG_MIPS_DECSTATION" = "y" ]; then
+if [ "$CONFIG_DECSTATION" = "y" ]; then
bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL
- comment 'Assuming little endian code required.'
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 n
bool 'Networking support' CONFIG_NET
-bool 'Limit memory to low 16MB' CONFIG_MAX_16M
-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
endmenu
@@ -103,7 +62,11 @@ if [ "$CONFIG_MODULES" = "y" ]; then
fi
endmenu
-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
@@ -115,7 +78,27 @@ comment 'SCSI support'
tristate 'SCSI support' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
- source drivers/scsi/Config.in
+ if [ "$CONFIG_SGI" = "n" ]; then
+ source drivers/scsi/Config.in
+ else
+ 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
+ fi
fi
endmenu
@@ -125,50 +108,74 @@ 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 'ISDN subsystem'
+if [ "$CONFIG_SGI" = "n" ]; then
+ mainmenu_option next_comment
+ comment 'ISDN subsystem'
-tristate 'ISDN support' CONFIG_ISDN
-if [ "$CONFIG_ISDN" != "n" ]; then
- source drivers/isdn/Config.in
-fi
-endmenu
+ 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)'
+ 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
+ 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
+if [ "$CONFIG_SGI" = "n" ]; 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'
+ 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 '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
fi
-bool 'Cross compilation' CONFIG_CROSS_COMPILE
endmenu
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index bb3635c25..201e66b94 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -17,26 +17,14 @@ CONFIG_SNI_RM200_PCI=y
CONFIG_MIPS_JAZZ=y
#
-# CPU selection
-#
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_R6000 is not set
-CONFIG_CPU_R4X00=y
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_TLB_SHUTDOWN=y
-# CONFIG_OPTIMIZE_R4600 is not set
-
-#
# General setup
#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
CONFIG_ELF_KERNEL=y
CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
CONFIG_NET=y
-# CONFIG_MAX_16M is not set
-# CONFIG_SYSVIPC is not set
+CONFIG_SYSVIPC=y
#
# Loadable module support
@@ -53,7 +41,7 @@ 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 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
@@ -87,7 +75,7 @@ CONFIG_INET=y
# CONFIG_INET_RARP is not set
# CONFIG_NO_PATH_MTU_DISCOVERY is not set
CONFIG_IP_NOSR=y
-CONFIG_SKB_LARGE=y
+# CONFIG_SKB_LARGE is not set
#
#
@@ -99,50 +87,7 @@ CONFIG_SKB_LARGE=y
#
# SCSI support
#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-CONFIG_SCSI_EATA_DMA=y
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI is not set
#
# Network device support
@@ -152,22 +97,12 @@ CONFIG_NETDEVICES=y
# 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=y
CONFIG_LANCE32=y
# CONFIG_NET_VENDOR_SMC is not set
-CONFIG_NET_ISA=y
-# CONFIG_E2100 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_EWRK3 is not set
-# CONFIG_EEXPRESS is not set
-# CONFIG_HPLAN_PLUS is not set
-# CONFIG_HPLAN is not set
-# CONFIG_HP100 is not set
-# CONFIG_NE2000 is not set
-# CONFIG_NI52 is not set
-# CONFIG_NI65 is not set
-# CONFIG_SK_G16 is not set
+# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
@@ -176,17 +111,6 @@ CONFIG_NET_ISA=y
# CONFIG_NET_RADIO is not set
# CONFIG_SLIP is not set
# CONFIG_TR is not set
-CONFIG_MIPS_JAZZ_SONIC=y
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
#
# Filesystems
@@ -194,7 +118,7 @@ CONFIG_MIPS_JAZZ_SONIC=y
# CONFIG_QUOTA is not set
# CONFIG_MINIX_FS is not set
# CONFIG_EXT_FS is not set
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=y
# CONFIG_XIA_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
@@ -213,29 +137,13 @@ CONFIG_ISO9660_FS=y
# CONFIG_UFS_FS is not set
#
-# Character devices
-#
-CONFIG_SERIAL=y
-# CONFIG_DIGI is not set
-# CONFIG_CYCLADES is not set
-# CONFIG_STALDRV is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_PRINTER is not set
-# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_FTAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-
-#
-# Sound
+# SGI Character Devices
#
-# CONFIG_SOUND is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_SGI_SERIAL is not set
#
# Kernel hacking
#
+# CONFIG_REMOTE_DEBUG is not set
# CONFIG_PROFILE is not set
-CONFIG_CROSS_COMPILE=y
diff --git a/arch/mips/deskstation/Makefile b/arch/mips/deskstation/Makefile
index 8e1b6bb13..903a73eb0 100644
--- a/arch/mips/deskstation/Makefile
+++ b/arch/mips/deskstation/Makefile
@@ -13,7 +13,7 @@
all: deskstation.o
O_TARGET := deskstation.o
-O_OBJS := hw-access.o int-handler.o setup.o
+O_OBJS := hw-access.o int-handler.o reset.o setup.o
int-handler.o: int-handler.S
diff --git a/arch/mips/deskstation/hw-access.c b/arch/mips/deskstation/hw-access.c
index 2d79e6f77..418bac5f6 100644
--- a/arch/mips/deskstation/hw-access.c
+++ b/arch/mips/deskstation/hw-access.c
@@ -13,16 +13,17 @@
#include <linux/linkage.h>
#include <linux/types.h>
#include <asm/bootinfo.h>
-#include <asm/cache.h>
+#include <asm/cachectl.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/mc146818rtc.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.
*/
@@ -110,24 +111,21 @@ fd_disable_irq(void)
void
deskstation_fd_cacheflush(const void *addr, size_t size)
{
- cacheflush(addr, size, CF_DCACHE|CF_ALL);
+ flush_cache_all();
}
/*
- * RTC stuff (This is a guess on how Deskstation handles this ...)
+ * RTC stuff
*/
-static unsigned char
-rtc_read_data(unsigned long addr)
+static unsigned char *
+rtc_read_data()
{
- outb_p(addr, RTC_PORT(0));
- return inb_p(RTC_PORT(1));
+ return 0;
}
static void
-rtc_write_data(unsigned char data, unsigned long addr)
+rtc_write_data(unsigned char data)
{
- outb_p(addr, RTC_PORT(0));
- outb_p(data, RTC_PORT(1));
}
/*
diff --git a/arch/mips/deskstation/int-handler.S b/arch/mips/deskstation/int-handler.S
index a52df711f..d7ff36d0f 100644
--- a/arch/mips/deskstation/int-handler.S
+++ b/arch/mips/deskstation/int-handler.S
@@ -15,9 +15,9 @@
.set noreorder
.set noat
.align 5
- NESTED(deskstation_handle_int, FR_SIZE, sp)
+ NESTED(deskstation_handle_int, PT_SIZE, sp)
SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
+ REG_S sp,PT_OR2(sp)
CLI
.set at
lui s0,%hi(PORT_BASE)
diff --git a/arch/mips/deskstation/reset.c b/arch/mips/deskstation/reset.c
new file mode 100644
index 000000000..7fb387631
--- /dev/null
+++ b/arch/mips/deskstation/reset.c
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/mips/deskstation/process.c
+ *
+ * Reset a Deskstation.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+
+void
+jazz_hard_reset_now(void)
+{
+ printk("Implement jazz_hard_reset_now().\n");
+ printk("Press reset to continue.\n");
+ while(1);
+}
diff --git a/arch/mips/deskstation/setup.c b/arch/mips/deskstation/setup.c
index fedab9c84..59d3da401 100644
--- a/arch/mips/deskstation/setup.c
+++ b/arch/mips/deskstation/setup.c
@@ -17,7 +17,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
-#include <asm/processor.h>
#include <asm/vector.h>
/*
@@ -34,6 +33,7 @@ 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_hard_reset_now(void);
#ifdef CONFIG_DESKSTATION_TYNE
unsigned long mips_dma_cache_size = 0;
@@ -43,6 +43,10 @@ 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);
@@ -58,6 +62,10 @@ rpc44_irq_setup(void)
* 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);
@@ -65,46 +73,9 @@ rpc44_irq_setup(void)
}
#endif
-void (*board_time_init)(struct irqaction *irq);
-
-static void deskstation_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);
-}
-
void
deskstation_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;
- }
- }
-
switch(mips_machtype) {
#ifdef CONFIG_DESKSTATION_TYNE
case MACH_DESKSTATION_TYNE:
@@ -115,9 +86,8 @@ deskstation_setup(void)
memcpy(&mips_dma_cache_base, TAGVALPTR(atag), atag->size);
irq_setup = tyne_irq_setup;
- feature = &deskstation_tyne_feature; // Will go away
- port_base = PORT_BASE_TYNE;
- isa_slot_offset = 0xe3000000;
+ feature = &deskstation_tyne_feature;
+ isa_slot_offset = 0xe3000000; // Will go away
break;
#endif
#ifdef CONFIG_DESKSTATION_RPC44
@@ -125,17 +95,12 @@ deskstation_setup(void)
irq_setup = rpc44_irq_setup;
mips_memory_upper = KSEG0 + (32 << 20); /* xxx fixme imp */
feature = &deskstation_rpc44_feature; // Will go away
- port_base = PORT_BASE_RPC44;
isa_slot_offset = 0xa0000000;
break;
#endif
}
- board_time_init = deskstation_time_init;
fd_cacheflush = deskstation_fd_cacheflush;
request_region(0x00,0x20,"dma1");
request_region(0x40,0x20,"timer");
request_region(0x70,0x10,"rtc");
-
- if (mips_machtype == MACH_DESKSTATION_RPC44)
- EISA_bus = 1;
}
diff --git a/arch/mips/doc/mmimpl/openbsd b/arch/mips/doc/mmimpl/openbsd
new file mode 100644
index 000000000..f393b2b98
--- /dev/null
+++ b/arch/mips/doc/mmimpl/openbsd
@@ -0,0 +1,300 @@
+Each instance of software process mapping state holds:
+
+ Reference count
+
+ Access control lock
+
+ Statistic info
+
+ pmap ASID
+
+ global ASID generation comparator
+
+ array of pages of R4K PTE's
+
+The control structure looks like the following:
+
+typedef struct pmap {
+ int pm_count; /* pmap reference count */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+ int pm_tlbpid; /* address space tag */
+ u_int pm_tlbgen; /* TLB PID generation number */
+ struct segtab *pm_segtab; /* pointers to pages of PTEs */
+} *pmap_t;
+
+The PTE array is sized only to be able to map userspace, it looks
+like this:
+
+#define PMAP_SEGTABSIZE 512
+
+typedef union pt_entry {
+ unsigned int pt_entry; /* for copying, etc. */
+ struct pte pt_pte; /* for getting to bits by name */
+} pt_entry_t; /* Mach page table entry */
+
+struct segtab {
+ union pt_entry *seg_tab[PMAP_SEGTABSIZE];
+};
+
+All user processes have pm_segtab point to a block of memory for this
+array. The special kernel pmap has a NULL pm_segtab, this is how you
+can tell if you are adding/removing mappings to the kernel or not.
+
+At boot time INIT gets pmap ASID 1 and the current global tlbpid_gen
+value for it's generation comparator. All other new processes get a
+pmap ASID and comparator of 0 which will always require the allocation
+of a new ASID when this process is first scheduled.
+
+To find a PTE within the R4K PTE array given a user virtual address
+and a software pmap extract like this:
+
+ --------------------------------------------
+User VADDR | 0 | array elem | PTE within PAGE | 0 |
+ --------------------------------------------
+ 31 30 22 21 12 11 0
+For example:
+
+pte_t *vaddr_to_pte(pmap_t pmap, unsigned long vaddr)
+{
+ int entry;
+ pte_t *pte;
+
+ entry = (vaddr >> 22) & 0x1ff;
+ pte = pmap->pm_segtab->seg_tab[entry];
+ return pte + ((vaddr >> 12) & 0x3ff);
+}
+
+To destroy a process mapping.
+
+1) Decrement pmap reference count
+
+2) If reference count is now zero and pmap has pm_segtab
+
+ a) check each seg_tab array entry
+
+ b) if non-NULL, flush the page from the cache,
+ free the page, and mark seg_tab[xxx] to NULL
+
+ c) Free pm_segtab array and set pm_segtab to NULL
+
+ASID allocation
+
+ This happens only at switch() time, pmap_alloc_tlbpid()
+ is called and is passed a ptr to the proc being switched
+ to.
+
+ The global tlbpid_gen counter is compared against the
+ pm_tlbgen in the pmap for this process. When the generation
+ changes and the pmap gen does not match, a new asid needs
+ to be allocated to the process.
+
+ The idea is that when the entire tlb is flushed, you go to
+ another generation. So you see things go like this:
+
+Boot time: tlbpid_gen = 1
+ tlbpid_cnt = 2
+
+INIT task: pm_tlbpid = 1
+ pm_tlbgen = tlbpid_gen
+
+ When INIT hits the cpu for the first time, it's pm_tlbgen will
+ match tlbpid_gen and therefore it's pm_tlbpid of 1 will be
+ used as the ASID when control is passed back to switch().
+ Let's say another task is forked off my init.
+
+New task: pm_tlbpid = 0
+ pm_tlbgen = 0
+
+ When this task hits the cpu for the first time, since a tlbgen
+ of zero will never match tlbpid_gen, it is allocated a new ASID
+ which is the current value of tlbpid_cnt. tlbpid_cnt is now
+ incremented. When tlbpid_cnt grows larger than the number
+ of ASIDS supported by the MMU, the entire TLB is flushed and
+ this task instead gets a tlbpid of 1 and tlbpid_gen is
+ incremented causing all other tasks to require a new ASID
+ when they are switch()'d to next.
+
+ The idea is that reallocating an ASID for a task would be too
+ expensive if it required searching for the previous ASID in the
+ current set of TLB entires. It is cheaper just to flush the
+ entire TLB and require everyone to get a new ASID when this
+ overflow happens. But in between overflows, and thus while
+ tlbpid_gen is the same, a process retains it's ASID for each
+ invocation of switch() for which it is scheduled.
+
+Adding a new entry into a processes pmap is pretty straight forward:
+
+ a) Given a pmap, a virtual address, a physical page,
+ a set of protections and a wired true/false value
+ we decide what to do.
+
+ b) If this is real physical RAM (as opposed to device
+ memory, IS_VM_PHYSADDR(pa) tells the case) we do
+ the following.
+
+ Set up the pte page permissions:
+
+ a) if the protections passed do not indicate
+ write protection, make it a read-only pte
+ which is MIPS terms is
+
+ (PG_RDONLY | PG_VALID | PG_CACHED)
+
+ The PG_RDONLY is a software bit which is masked
+ out at tlb refill time (discussed later).
+
+ b) if the protections do indicate the mapping
+ to be entered is indeed writable we setup
+ the pte based upon whether this is going into
+ the kernel map or a user map
+
+ For kernel map we just allow the page to be
+ written to from the get go, and clear the PG_CLEAN
+ flag for the page_struct this physical page is
+ represented by, end of story.
+
+ For a user, we only allow writes from the start
+ if the page_struct is already not clean, else
+ we don't set the MIPS pte dirty bit.
+
+ The page is marked valid and cachable no matter what.
+
+ Enter the new mapping into the pv_list (discussed later).
+
+ c) If this is a mapped device then use PG_IOPAGE permissions,
+ if not writable clear the dirty MIPS pte bit, clear the global
+ bit (which is set in the PG_IOPAGE expansion) in all cases.
+
+ d) If this is an executable page, push the page out of
+ the instruction cache.
+
+ MIPS is funny in that all cache operations perform an
+ address translation, so you have to be careful. OpenBSD
+ uses the KSEG0 address (which does not go through the
+ TLB to be translated) for these ICACHE flushes. The indexed
+ primary icache flush is used to remove the lines from the
+ cache.
+
+ e) If this is a kernel mapping (pmap->pm_segtab is NULL), get
+ the pte_t ptr from kernel_regmap storage, or in the physical
+ page number and (PG_ROPAGE | PG_G) (XXX why all the time?),
+ set the wired bit and increment the wired count if the wired
+ boolean arg was true, increment the resident count if the
+ pte was previously invalid, call tlbupdate to get rid of
+ any previous mapping, and set pte->pt_entry to this new pte
+ value.
+
+ f) For user we need to check first if the PTE array points to
+ a page yet. If not we need to get a zero page. Calculate
+ the offset into the appropriate page based upon virtual
+ address, or in the virtual page in the new pte value,
+ increment wired and resident count if necessary, and
+ set pte->pte_entry to this new pte value. Finally, if
+ the process has (potentially) a valid ASID (and therefore
+ entries in the TLB right now, ie. pmap->pm_tlbgen ==
+ tlbpid_gen) then remote any matching enties in the TLB
+ for this processes virtual-page/ASID pair.
+
+The kernel keeps a pv_list, it has one entry for each managed physical
+page in the system. Off each entry is a linked list, one for each
+virtual page to which the entries physical page is mapped, the list
+head counts as the first entry. This list is used to detect cache
+aliasing problems with virtual caches.
+
+When the kernel adds a new element to a physical pages pv_list entry,
+it checks whether this new virtual mapping could cause a cache alias,
+if so then it marks all of the virtual pages in the list uncacheable.
+The reason this is done is simple:
+
+ Suppose a process has physical page X mapped at two virtual
+ addresses within it's address space, called Y and Z. Y and
+ Z could potentially be in the cache at the same time due to
+ the way their two addresses index entries in the virtual
+ cache. The process could bring both pages into the cache,
+ write to mapping Y, then read the same datum from mapping
+ Z and it would see the old data.
+
+Also, when a mapping is removed (discussed in a bit) the kernel
+rechecks the pv_list to see if the physical pages mappings were marked
+uncachable and if so, it runs through the list without the mapping now
+being removed to see if the alias is no longer present. If no alias
+exists any more, all the virtual pages in the pv_list are mapped
+cachable again.
+
+The pv_list is also checked when the kernel changes permissions
+on an extent of user virtual address space within a pmap.
+
+Mappings are removed from a processes pmap in the following manner:
+
+ Kernel is told the pmap, beginning virtual address, and
+ ending virtual address in which to perform the de-map
+ operation. First the kernel case.
+
+ For each pte within the given range, if the pte for that
+ page is not marked valid we skip it. If it is valid, first
+ we decrement the resident count unconditionally, and decrement
+ the wired count if the entry was marked with the wired
+ attribute. Next the pv_list is consulted as discussed above,
+ and if the mapping was the last pv_list element for the
+ assosciated physical page, then the cache is flushed of the
+ data. Finally, the pte is marked invalid, retaining the
+ global bit, and the tlb is flushed of the entry if still
+ present within the mmu hardware.
+
+ On the user end of things, do the same as the kernel case,
+ except that the mmu TLB hardware is only flushed of each
+ entry if the pmap in question (potentially) holds a valid
+ ASID by way of pmap->pm_tlbgen being equal to tlbpid_gen.
+
+Changes occur to a range of virtual addresses within a processes pmap
+in two slightly different ways. In on way, the protection of a single
+page is lowered from what it is currently. The second way moves the
+protection of a virtual address region to an arbitrary direction,
+either more strict or less strict.
+
+In the first case, the kernel is given a physical address and a new
+protection value. If the protection is full blast read/write/execute,
+or just read+write, nothing is done because the existing protections
+will always be equal to this new protection (this procedure is only
+invoked to lower permissions). If a read only type protection is
+being requested, the pv_list for this physical address is walked and
+each virtual/pmap mapping is set to the requested protection.
+Finally, if the read attribute is not set in the new protection, all
+virtual mappings in the physical pages pv_list are removed one at a
+time via the method described above. This first case, when just
+changing protections and not removing them, calls the next procedure
+to do the actual work on each mapping.
+
+Next, we are given a pmap, a virtual range extent, and the new
+protections to apply to that particular range. Since this can be
+called externally and not just by the per-page protection lowering
+method just described, we handle the null protection request by
+removing the mappings completely from the pmap. For the kernel pmap
+we cycle throught the virtual addresses, and change the software copy
+of the valid pte's to have the new protection then update the mmu TLB
+hardware. For the user, we act similarly except that the TLB hardware
+update is only performed if the pm_tlbgen for the pmap matches the
+global tlbpid_gen comparator.
+
+The kernel can be asked to change the cachable attribute for an
+arbitrarily mapped physical page. This is implemented just like the
+page protection code just described, the pv_list is walked down and
+the cachable "protection" bit(s) are modified as asked. This is
+mainly used by the pv_list alias detection code to fix mappings which
+will end up causing aliases, or are detected to no longer cause an
+alias due to one of the virtual mappings being removed.
+
+The physical address backed by a given pmap/virtual-address pair can
+be asked for as well. There is a method which performs this as well,
+retaining the non-page offset bits in the return value if a virtual
+to physical translation can be found, else NULL is returned.
+
+Finally, two methods are provided to control the copying and
+zero-clearing out of pages which will be (or already are) mapped
+within someone(s) per-process pmap. This can be used when it is
+necessary to create a temporary mapping for the operation or do
+special things to keep caches consistant for example.
+
+
+
diff --git a/arch/mips/doc/pagetables.txt b/arch/mips/doc/pagetables.txt
deleted file mode 100644
index 3d900a194..000000000
--- a/arch/mips/doc/pagetables.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-Format and handling of Linux/MIPS pagetables
-============================================
-
-This file describes the MIPS specific parts of the Linux pagetable handling.
-
-Opposed to other architecures like i386 or m68k architecture all MIPS
-CPUs only implement the TLB itself and a small set of functions to
-maintain it as hardware. The actual maintenance of the TLB's contents
-is implemented in software only.
-
-The TLB has a relativly small number of entries. This limits the
-maximum address space that can mapped by the TLB using 4kb pages and
-without consideration of wired entries to a maximum of 512kb for the
-R1000, 384kb for the R4000/4400 and 256kb for the R2000/R3000. This
-actual size of mappable space is even smaller due to the wired entries.
-
-Especially for processes with a huge working set of pages it is therefore
-important to make the process of reloading entries into the TLB as
-efficient as possible. This means:
-
- - Choosing a data structure that can be handled as efficient as
- possible.
- - The implementation of the low level pagefault handling has to be
- implemented in a efficient way.
-
-The Linux kernel itself implements three level page tables as a tree
-structure. Linux implementations that don't need three levels of page
-tables can fold one level of the page tables so that effectivly a two
-level page table remains. The exact size and content of the entries
-is upto the implementation.
-
-Opposed to this the MIPS hardware architecture implies by the data
-provided in the c0_context/c0_xcontext registers a simple array of
-4 byte elements (for R2000/R3000/R6000) or 8 byte elements (for the
-other 64bit members of the CPU family).
-
-The page tables are mapped to the address TLBMAP (which is usually
-defined as 0xe4000000 in <asm/mipsconfig.h). The page which contains
-the root of the page table of the current process, the "page directory"
-and is therefore mapped at (TLBMAP + (TLBMAP >> (12-2))) (this is the
-value of the define TLB_ROOT which is defined as 0xe4390000). That
-way the kernel itself can access the page tables as a tree structure
-while the exception handlers can work with maxiumum efficiency accessing
-the page tables as simple array.
-
-The tlb refill handler itself is very simple. For the R4x00 family it
-has just 14 instruction, for the R4600 and derivatives it can be
-optimized to 12 instruction, even further for the R10000. This
-exception handler is very simple and fast and therefore doesn't any
-checking for errors or special cases.
-
-It can therefore happen that the entry that is attempted to be reloaded
-isn't mapped via the pagetables thus resulting in a double tlb refill
-exception. Due to the EXL flag set in c0_status this exception goes
-through the general exception vector and from there to handle_tlbl.
-Handle_tlbl is a more complex exception handler that is - compared
-to the first handler - complex and called far less often. It features
-handling of special cases and some error checking for debugging. This
-second handler still doesn't reenable interrupts, change to the kernel
-stack or save registers to be as efficient as possible. Therefore
-only the two registers k0/k1 are available for use. All this is only
-done when do_page_fault() in arch/mips/mm/fault.c is called. For the
-normal case this handler just reloads the entry mapping the pte table
-which again contains the entries to be loaded in the tlb. Since the
-original fault address has been lost this exception handler cannot
-complete the job. So it just returns to the main program which after
-taking another exception via the first tlb refill handler reloads the
-originally missing entry into the TLB and continues normal execution.
-
-Another special in the Linux/MIPS page handling is the handling of
-pages in non-existant branches of the page tables. To avoid that
-the exception handlers have to handle this special case the kernel
-maps these ptes (page table entries) to invalid_pte_table. This is a
-4kb page full of invalid entries. On an attempted access to such an
-invalid page the kernel then reloads - eventuall via a double fault
-this invalid entry into the tlb. The CPU then takes a tlb invalid
-exception resulting in a call to do_page_fault() which usually will
-take the apropriate measures like sending SIGSEGV.
-
-Downsides of this implementation are it's complexity and the faster
-handling of the majority of exceptions is bought at the expense of
-having to handle page aliasing problems with the page tables (which
-are accessed at TLBMAP and in KSEG1) itself. This is done using
-uncached accesses which are especially on older machines with slow
-memory subsystems painfully slow. The implementation is done this
-way because for the original hardware which Linux/MIPS was intended for
-had a blindingly fast memory interface.
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index 3ee478fee..3868b60cf 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -13,7 +13,7 @@
all: jazz.o
O_TARGET := jazz.o
-O_OBJS := hw-access.o int-handler.o jazzdma.o setup.o
+O_OBJS := hw-access.o int-handler.o jazzdma.o reset.o setup.o
ifdef CONFIG_VIDEO_G364
O_OBJS += g364.o
diff --git a/arch/mips/jazz/hw-access.c b/arch/mips/jazz/hw-access.c
index 112941275..52a61165f 100644
--- a/arch/mips/jazz/hw-access.c
+++ b/arch/mips/jazz/hw-access.c
@@ -10,11 +10,12 @@
#include <linux/delay.h>
#include <linux/linkage.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/addrspace.h>
-#include <asm/cache.h>
#include <asm/vector.h>
#include <asm/jazz.h>
#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
#include <asm/mc146818rtc.h>
static unsigned char
@@ -102,7 +103,7 @@ fd_disable_irq(void)
void
jazz_fd_cacheflush(const void *addr, size_t size)
{
- cacheflush((unsigned long)addr, size, CF_DCACHE|CF_ALL);
+ flush_cache_all();
}
static unsigned char
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
index 03c999124..7be6b8457 100644
--- a/arch/mips/jazz/int-handler.S
+++ b/arch/mips/jazz/int-handler.S
@@ -22,10 +22,10 @@
*/
.set noreorder
- NESTED(jazz_handle_int, FR_SIZE, ra)
+ NESTED(jazz_handle_int, PT_SIZE, ra)
.set noat
SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
+ REG_S sp,PT_OR2(sp)
CLI
.set at
@@ -89,7 +89,7 @@ ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
* whistles and bells and we're aware of the problem.
*/
ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK
- lui s0,%hi(PORT_BASE_JAZZ)
+ lui s0,%hi(JAZZ_PORT_BASE)
li s1,1
andi t0,a0,8 # which pic?
bnez t0,ack_second
@@ -98,17 +98,17 @@ ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK
/*
* Acknowledge first pic
*/
- lb t2,%lo(PORT_BASE_JAZZ)+0x21(s0)
+ 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(PORT_BASE_JAZZ)+0x21(s0)
+ sb t0,%lo(JAZZ_PORT_BASE)+0x21(s0)
lui s3,%hi(intr_count)
lw t0,%lo(intr_count)(s3)
li t2,0x20
- sb t2,%lo(PORT_BASE_JAZZ)+0x20(s0)
+ sb t2,%lo(JAZZ_PORT_BASE)+0x20(s0)
/*
* Now call the real handler
*/
@@ -123,7 +123,7 @@ ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK
/*
* Unblock first pic
*/
- lbu a0,%lo(PORT_BASE_JAZZ)+0x21(s0)
+ lbu a0,%lo(JAZZ_PORT_BASE)+0x21(s0)
lb a0,%lo(cache_21)(s4)
subu t0,1
sw t0,%lo(intr_count)(s3)
@@ -131,24 +131,24 @@ ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK
and a0,s1
sb a0,%lo(cache_21)(s4)
jr v0
- sb a0,%lo(PORT_BASE_JAZZ)+0x21(s0) # delay slot
+ sb a0,%lo(JAZZ_PORT_BASE)+0x21(s0) # delay slot
.align 5
ack_second: /*
* Acknowledge second pic
*/
- lbu t2,%lo(PORT_BASE_JAZZ)+0xa1(s0)
+ 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(PORT_BASE_JAZZ)+0xa1(s0)
+ sb t3,%lo(JAZZ_PORT_BASE)+0xa1(s0)
li t3,0x20
- sb t3,%lo(PORT_BASE_JAZZ)+0xa0(s0)
+ sb t3,%lo(JAZZ_PORT_BASE)+0xa0(s0)
lui s3,%hi(intr_count)
lw t0,%lo(intr_count)(s3)
- sb t3,%lo(PORT_BASE_JAZZ)+0x20(s0)
+ sb t3,%lo(JAZZ_PORT_BASE)+0x20(s0)
/*
* Now call the real handler
*/
@@ -165,7 +165,7 @@ ack_second: /*
/*
* Unblock second pic
*/
- lb a0,%lo(PORT_BASE_JAZZ)+0xa1(s0)
+ lb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0)
lb a0,%lo(cache_A1)(s4)
subu t0,1
sw t0,%lo(intr_count)(s3)
@@ -173,7 +173,7 @@ ack_second: /*
and a0,s1
sb a0,%lo(cache_A1)(s4)
jr v0
- sb a0,%lo(PORT_BASE_JAZZ)+0xa1(s0) # delay slot
+ sb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0) # delay slot
/*
* Hmm... This is not just a plain PC clone so the question is
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index 3663f33d8..470185266 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -11,7 +11,7 @@
*/
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <asm/cache.h>
+#include <linux/mm.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/jazz.h>
@@ -19,6 +19,7 @@
#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.
@@ -41,8 +42,7 @@ static int debuglvl = 3;
* 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)
+static inline void vdma_pgtbl_init(void)
{
int i;
unsigned long paddr = 0;
@@ -69,7 +69,7 @@ unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
*/
vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
- cacheflush(vdma_pagetable_start, VDMA_PGTBL_SIZE, CF_DCACHE|CF_ALL);
+ flush_cache_all();
/*
* Clear the R4030 translation table
diff --git a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c
new file mode 100644
index 000000000..a0accc3f6
--- /dev/null
+++ b/arch/mips/jazz/reset.c
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/mips/acn/process.c
+ *
+ * Reset a Jazz machine.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+
+void
+jazz_hard_reset_now(void)
+{
+ printk("Implement jazz_hard_reset_now().\n");
+ printk("Press reset to continue.\n");
+ while(1);
+}
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index c5f5b1d77..6aaa2af75 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -11,10 +11,8 @@
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
-#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <asm/jazz.h>
-#include <asm/processor.h>
#include <asm/vector.h>
#include <asm/io.h>
@@ -31,8 +29,7 @@ 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 (*ibe_board_handler)(struct pt_regs *regs);
-extern void (*dbe_board_handler)(struct pt_regs *regs);
+extern void jazz_hard_reset_now(void);
static void
jazz_irq_setup(void)
@@ -47,91 +44,22 @@ jazz_irq_setup(void)
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);
}
-void (*board_time_init)(struct irqaction *irq);
-
-static void jazz_time_init(struct irqaction *irq)
-{
- /* set the clock to 100 Hz */
- r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
- setup_x86_irq(0, irq);
-}
-
-/*
- * 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.
- * We should try to handle this case a bit more gracefully than just
- * zapping the process ...
- */
-static void jazz_be_board_handler(struct pt_regs *regs)
-{
- u32 jazz_is, jazz_ia;
-
- /*
- * Give some debugging aid ...
- */
- jazz_is = r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE);
- jazz_ia = r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);
- printk("Interrupt Source == %08x\n", jazz_is);
- printk("Invalid Address Register == %08x\n", jazz_ia);
- show_regs(regs);
-
- /*
- * Assume it would be too dangerous to continue ...
- */
- force_sig(SIGBUS, current);
-}
-
void
jazz_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;
- }
- }
irq_setup = jazz_irq_setup;
- board_time_init = jazz_time_init;
fd_cacheflush = jazz_fd_cacheflush;
feature = &jazz_feature; // Will go away
- port_base = PORT_BASE_JAZZ;
isa_slot_offset = 0xe3000000;
request_region(0x00,0x20,"dma1");
request_region(0x40,0x20,"timer");
/* The RTC is outside the port address space */
-
- if (mips_machtype == MACH_MIPS_MAGNUM_4000
- && mips_machtype == MACH_OLIVETTI_M700)
- EISA_bus = 1;
- /*
- * The Jazz hardware provides additional information for
- * bus errors, so we use an special handler.
- */
- ibe_board_handler = jazz_be_board_handler;
- dbe_board_handler = jazz_be_board_handler;
+ hard_reset_now = jazz_hard_reset_now;
}
diff --git a/arch/mips/kernel/.cvsignore b/arch/mips/kernel/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/kernel/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index b76c723b2..e537ac73e 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,9 +14,24 @@
all: kernel.o head.o
EXTRA_ASFLAGS = -mips3 -mcpu=r4000
O_TARGET := kernel.o
-O_OBJS := branch.o 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 ksyms.o \
- unaligned.o tags.o
+O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
+ ioport.o setup.o syscall.o sysmips.o bios32.o ipc.o ksyms.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
+
+#
+# SGI's have very different interrupt/timer hardware.
+#
+ifndef CONFIG_SGI
+O_OBJS += irq.o time.o
+endif
+
+#
+# Do we want to be able to execute IRIX elf binaries?
+#
+ifdef CONFIG_BINFMT_IRIX
+O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o
+endif
#
# Kernel debugging
@@ -43,9 +58,27 @@ O_OBJS := $(sort $(O_OBJS))
all: kernel.o head.o
entry.o: entry.S
-exception.o: exception.S
+
head.o: head.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:
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 32705b320..a1e302711 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 1997 by Ralf Baechle
*/
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 6072afae2..515f9af13 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -18,8 +18,10 @@
#include <asm/asm.h>
#include <asm/errno.h>
+#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
+#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/stackframe.h>
#include <asm/processor.h>
@@ -39,115 +41,98 @@ 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
handle_bottom_half:
lui s0,%hi(intr_count)
lw s1,%lo(intr_count)(s0)
mfc0 s3,CP0_STATUS # Enable IRQs
- addiu s2,s1,1
+ 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 t0,CP0_STATUS
+
mtc0 s3,CP0_STATUS # Restore old IRQ state
+
b 9f
- sw s1,%lo(intr_count)(s0) # delay slot
+ sw s1,%lo(intr_count)(s0)
+
+reschedule:
+ jal schedule
+ nop
-reschedule: jal schedule
- nop # delay slot
EXPORT(ret_from_sys_call)
lw t0,intr_count # bottom half
bnez t0,return
-
-9: lw t0,bh_mask # delay slot
+9:
+ lw t0,bh_mask
lw t1,bh_active # unused delay slot
and t0,t1
bnez t0,handle_bottom_half
+ 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
- mfc0 t0,CP0_STATUS # delay slot
lw t1,need_resched
ori t0,0x1f # enable irqs
xori t0,0x1e
bnez t1,reschedule
- mtc0 t0,CP0_STATUS # delay slot
+ mtc0 t0,CP0_STATUS
- lw s0,current
+ lw s0,current_set
lw t0,task
lw a0,blocked(s0)
+
beq s0,t0,return # task[0] cannot have signals
- # save blocked in a0 for
- # signal handling
- lw t0,signal(s0) # delay slot
+ lw t0,signal(s0) # save blocked in a0 for signals
+
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
+ eret
.set at
/*
- * Beware: timer_interrupt, interrupt, fast_interrupt and bad_interrupt
- * have unusual calling conventions to speedup the mess.
+ * Beware: interrupt, fast_interrupt and bad_interrupt have unusual
+ * calling conventions to speedup the mess.
*
* a0 - interrupt number
* s2 - destroyed
* return values:
* v0 - return routine
- *
- * 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.
*/
.text
.set at
.align 5
-NESTED(timer_interrupt, FR_SIZE, sp)
- move s2,ra
- jal do_IRQ
- move a1,sp # delay slot
- .set reorder
- la v0,ret_from_sys_call
- jr s2
- .set noreorder
- END(timer_interrupt)
-
- .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
+
jal do_IRQ
- move a1,sp # delay slot
+ move a1,sp
+
mfc0 t0,CP0_STATUS # disable IRQs
ori t0,1
xori t0,1
@@ -159,10 +144,12 @@ NESTED(interrupt, FR_SIZE, sp)
END(interrupt)
.align 5
-NESTED(fast_interrupt, FR_SIZE, sp)
- .set reorder
+NESTED(fast_interrupt, PT_SIZE, sp)
move s2,ra
jal do_fast_IRQ
+ nop
+
+ .set reorder
la v0,return
jr s2
.set noreorder
@@ -172,12 +159,11 @@ NESTED(fast_interrupt, FR_SIZE, sp)
* Don't return & unblock the pic
*/
LEAF(bad_interrupt)
- .set reorder
lw t0,%lo(intr_count)(s3)
subu t0,1
- .set noreorder
+
j return
- sw t0,%lo(intr_count)(s3) # delay slot
+ sw t0,%lo(intr_count)(s3)
END(bad_interrupt)
.text
@@ -191,8 +177,9 @@ LEAF(spurious_interrupt)
lw t0,%lo(spurious_count)(t1)
la v0,return
addiu t0,1
+
jr ra
- sw t0,%lo(spurious_count)(t1)
+ sw t0,%lo(spurious_count)(t1)
END(spurious_interrupt)
/*
@@ -200,41 +187,28 @@ LEAF(spurious_interrupt)
* special handlers. If you didn't know yet - I *like* playing games with
* the C preprocessor ...
*/
-#define __BUILD_clear_none(exception) \
- REG_S sp,FR_ORIG_REG2(sp); /* sp < 0 */
-#define __BUILD_clear_sys(exception) \
- REG_S v0,FR_ORIG_REG2(sp); \
- REG_S a3,FR_ORIG_REG7(sp);
+#define __BUILD_clear_none(exception)
#define __BUILD_clear_fpe(exception) \
- REG_S sp,FR_ORIG_REG2(sp); /* sp < 0 */ \
cfc1 a1,fcr31; \
li a2,~(0x3f<<12); \
and a2,a1; \
ctc1 a2,fcr31;
-#define __BUILD_clear_watch(exception) \
- REG_S sp,FR_ORIG_REG2(sp); /* sp < 0 */ \
- mtc0 zero,CP0_WATCHLO; \
- mtc0 zero,CP0_WATCHHI
#define __BUILD_clear_ade(exception) \
- REG_S sp,FR_ORIG_REG2(sp); /* sp < 0 */ \
MFC0 t0,CP0_BADVADDR; \
- REG_S t0,FR_BADVADDR(sp);
+ REG_S t0,PT_BVADDR(sp);
#define __BUILD_silent(exception)
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-#define fmt "Got %s at %08x.\n"
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+
#define fmt "Got %s at %016Lx.\n"
-#endif
+
#define __BUILD_verbose(exception) \
la a1,8f; \
TEXT (#exception); \
- REG_L a2,FR_EPC(sp); \
+ 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; \
@@ -244,18 +218,19 @@ EXPORT(exception_count_##exception); \
#define BUILD_HANDLER(exception,handler,clear,verbose) \
.text; \
.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); \
- REG_S sp,FR_ORIG_REG2(sp); /* not a sys call */ \
+ li t0,-1; /* not a sys call */ \
+ REG_S t0,PT_OR2(sp); \
jal do_##handler; \
- move a0,sp; /* delay slot */ \
+ move a0,sp; \
j ret_from_sys_call; \
- nop; /* delay slot */ \
+ nop; \
END(handle_##exception)
BUILD_HANDLER(adel,ade,ade,silent) /* #4 */
@@ -270,7 +245,7 @@ EXPORT(exception_count_##exception); \
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,watch,verbose) /* #23 */
+ BUILD_HANDLER(watch,watch,none,verbose) /* #23 */
BUILD_HANDLER(vced,vced,none,verbose) /* #31 */
BUILD_HANDLER(reserved,reserved,none,verbose) /* others */
@@ -295,32 +270,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
- * FIXME: This table contains huge empty areas wasting memory.
*/
EXPORT(sys_narg_table)
- /*
- * Reserved space for all the SVR4, SVR, BSD43 and POSIX
- * flavoured syscalls.
- */
- .space (__NR_Linux)
-
- /*
- * Linux flavoured syscalls.
- */
#undef SYS
#define SYS(call, narg) .byte narg
+
+ /* Reserved space for all SVR4 flavoured syscalls. */
+ .space (1000)
+
+#ifdef CONFIG_BINFMT_IRIX
+ /* 32bit IRIX5 system calls. */
+#include "irix5sys.h"
+#else
+ .space (1000) /* No IRIX syscalls */
+#endif
+
+ /* Reserved space for all the BSD43 and POSIX syscalls. */
+ .space (2000)
+
+ /* Linux flavoured syscalls. */
#include "syscalls.h"
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 9b948a845..9bc35400b 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -9,6 +9,7 @@
#include <linux/sys.h>
#include <asm/asm.h>
+#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/regdef.h>
@@ -33,7 +34,8 @@
*/
lui k1,%hi(kernelsp)
lw k1,%lo(kernelsp)(k1)
-1: move k0,sp
+1:
+ move k0,sp
subu sp,k1,GDB_FR_SIZE
sw k0,GDB_FR_REG29(sp)
sw v0,GDB_FR_REG2(sp)
@@ -100,8 +102,9 @@
mfc0 v0,CP0_STATUS /* check if the FPU is enabled */
srl v0,v0,16
andi v0,v0,(ST0_CU1 >> 16)
+
beqz v0,2f /* disabled, skip */
- nop
+ nop
swc1 $0,GDB_FR_FPR0(sp)
swc1 $1,GDB_FR_FPR1(sp)
@@ -149,7 +152,8 @@
* current stack frame ptr
*/
-2: sw sp,GDB_FR_FRP(sp)
+2:
+ sw sp,GDB_FR_FRP(sp)
/*
* CP0 registers (R4000/R4400 unused registers skipped)
@@ -179,8 +183,9 @@
*/
move a0,sp
+
jal handle_exception
- nop
+ nop
/*
* restore all writable registers, in reverse order
@@ -207,8 +212,9 @@
mfc0 v0,CP0_STATUS /* check if the FPU is enabled */
srl v0,v0,16
andi v0,v0,(ST0_CU1 >> 16)
+
beqz v0,3f /* disabled, skip */
- nop
+ nop
lwc1 $31,GDB_FR_FPR31(sp)
lwc1 $30,GDB_FR_FPR30(sp)
@@ -247,7 +253,8 @@
* Now the CP0 and integer registers
*/
-3: mfc0 t0,CP0_STATUS
+3:
+ mfc0 t0,CP0_STATUS
ori t0,0x1f
xori t0,0x1f
mtc0 t0,CP0_STATUS
@@ -292,7 +299,7 @@
lw $1,GDB_FR_REG1(sp)
lw sp,GDB_FR_REG29(sp) /* Deallocate stack */
- ERET
+ eret
.set at
.set reorder
END(trap_low)
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index 9a3240152..13bf353ff 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -68,10 +68,10 @@
#include <linux/signal.h>
#include <linux/kernel.h>
-#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
-#include <asm/cache.h>
+#include <asm/segment.h>
+#include <asm/cachectl.h>
#include <asm/system.h>
#include <asm/gdb-stub.h>
@@ -326,7 +326,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 +337,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 +613,7 @@ void handle_exception (struct gdb_regs *regs)
* NB: We flush both caches, just to be sure...
*/
- cacheflush((void *)KSEG0, KSEG1-KSEG0, CF_BCACHE|CF_ALL);
+ flush_cache_all();
return;
/* NOTREACHED */
break;
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 82de12ff5..fa73c95bb 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -4,439 +4,621 @@
* 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
- * Additional R3000 support by Didier Frick <dfrick@dial.eunet.ch>
- * for ACN S.A, Copyright (C) 1996 by ACN S.A
+ * Further modifications by David S. Miller
*
* Head.S contains the MIPS exception handler and startup code.
- *
- * FIXME: Note that the #ifdef's for R4X00 assume R3000 is the #else
- * case, which is a little naughty. We also do NOT need the
- * dec_entry goo at the begining of all this - PMA
- * FIXME: This #ifdef stuff is ugly and I should move the tlb/exception
- * handler code out into some other file - Ralf
- * Take the zillions of (_MIPS_ISA == _MIPS_ISA_MIPSx) as a temporary
- * solution. I know how they look ...
*/
-#include <linux/config.h> /* For the DECstation hacks */
+#include <linux/config.h>
#include <linux/tasks.h>
-#include <asm/addrspace.h>
#include <asm/asm.h>
+#include <asm/offset.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/cache.h>
+#include <asm/segment.h>
+#include <asm/cachectl.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/stackframe.h>
#include <asm/bootinfo.h>
-
-#define PAGE_SIZE 0x1000
-
-/*
- * FIXME: I still think the following should be in an include file (see
- * also the reference in arch/mips/mips1/r3000.S - PMA
- */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-#define MODE_GLOBAL 0x0100 /* shared for all processes */
-#define MODE_ALIAS 0x00e0
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
-#define MODE_GLOBAL 0x0001 /* shared for all processes */
-#define MODE_ALIAS 0x0016 /* uncachable */
-#endif
-
-/*
- * The two symbols begin_except and end_except mark the range that is copied
- * to KSEG0 on startup.
- */
-EXPORT(begin_except)
- .text
+#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.
*
- * For some machine where the kernel doesn't get directly loaded to KSEG0
- * the exceptionhandler get copied to KSEG0. They therefore must be
- * relocatable code.
+ * 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
- */
- .set noreorder
- .set noat
- LEAF(except_vec0)
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- mfc0 k1,CP0_CONTEXT
- nop
- lw k0,(k1) # May cause another exception
- mfc0 k1,CP0_EPC # Get the return address
- srl k0,12 # Convert to EntryLo format
- mtc0 k0,CP0_ENTRYLO0
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- .set mips3
- 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
-#endif
-#ifndef CONFIG_OPTIMIZE_R4600
- nop # Needed for R4[04]00 pipeline
-#endif
- tlbwr
- nop # Needed for R4[04]00 pipeline
- nop
-#ifndef CONFIG_OPTIMIZE_R4600
- nop
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- jr k1
- rfe
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- eret
- /*
- * Partial workaround for R4000 bug. For explanation see
- * MIPS docs. Note that this that obscure that it wont
- * almost never happen. Well, but Mips writes about it's bugs.
- */
- nop
- eret
-#endif
- END(except_vec0)
-
-/******************************************************************************/
-
- /*
- * XTLB refill, EXL == 0
- * Should never be reached on R4000.
- */
- .org except_vec0+0x80
- NESTED(except_vec1, 0, sp)
- .set noat
- /*
- * Register saving is delayed as long as we don't know
- * which registers really need to be saved.
- */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- mfc0 k1,CP0_CONTEXT
- nop
- lw k0,(k1) # May cause another exception
- mfc0 k1,CP0_EPC # Get the return address
- srl k0,12 # Convert to EntryLo format
- mtc0 k0,CP0_ENTRYLO0
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- 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
-#endif
- nop # Needed for R4[04]00 pipeline
- tlbwr
- nop # Needed for R4[04]00 pipeline
- nop
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- jr k1
- rfe
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- nop
- eret
-#endif
- /*
- * Partial workaround for R4000 bug. For explanation see
- * MIPS docs. Note that this that obscure that it wont
- * almost never happen. Well, but Mips writes about it's bugs.
- */
- nop
- eret
- END(except_vec1)
-
-/******************************************************************************/
-
- /*
- * Cache Error
- */
- .org except_vec1+0x80
- LEAF(except_vec2)
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- /*
- * On the R3000, this is the "Uncached TLB Miss" handler.
- */
- j except_vec0
- nop
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- /*
- * Famous last words: unreached
- */
- mfc0 a1,CP0_ERROREPC
- PRINT("Cache error exception: c0_errorepc == %08x\n")
-1: j 1b
- nop
-#endif
- 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.
- * Except for k1 which MUST be preserved to allow
- * nested TLB refill exceptions on the R3000.
- */
- 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
-
-EXPORT(end_except)
-
-/******************************************************************************/
+ /* 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
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(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
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ 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
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ 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
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ srl k0, k0, 22
+ lw k1, THREAD_PGDIR(k1)
+ sll k0, k0, 2
+ addu k1, k1, k0
+ mfc0 k0, CP0_CONTEXT
+ lw k1, (k1)
+ srl k0, k0, 1
+ and k0, k0, 0xff8
+ addu k1, k1, k0
+ lw k0, 0(k1)
+ lw k1, 4(k1)
+ tlbp
+ srl k0, k0, 6
+ mtc0 k0, CP0_ENTRYLO0
+ srl k1, k1, 6
+ mfc0 k0, CP0_INDEX
+ mtc0 k1, CP0_ENTRYLO1
+ bltzl k0, 1f
+ tlbwr
+1:
+ nop
+ eret
+ END(except_vec0_r4k_mphwbug)
+#endif
+
+ /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */
+ LEAF(except_vec0_r4k_250MHZhwbug)
+ .set mips3
+ mfc0 k0, CP0_BADVADDR
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ 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
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ 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
+
+ /* TLB refill, EXL == 0, R[23]00 version */
+ LEAF(except_vec0_r2300)
+ .set mips1
+ mfc0 k0, CP0_BADVADDR
+ lui k1, %hi(current_set)
+ lw k1, %lo(current_set)(k1)
+ srl k0, k0, 22
+ lw k1, THREAD_PGDIR(k1)
+ sll k0, k0, 2
+ addu k1, k1, k0
+ mfc0 k0, CP0_CONTEXT
+ lw k1, (k1)
+ srl k0, k0, 1
+ and k0, k0, 0xffc
+ addu k1, k1, k0
+ lw k0, (k1)
+ srl k0, k0, 12
+ mtc0 k0, CP0_ENTRYLO0
+ mfc0 k1, CP0_EPC
+ tlbwr
+ nop
+ nop
+ nop
+ nop
+ jr k1
+ rfe
+ END(except_vec0_r2300)
+
+
+ /* XTLB refill, EXL == 0, R4xx0 cpus only use this... */
+ NESTED(except_vec1_generic, 0, sp)
+ .set noat
+ .set mips3
+ /* Register saving is delayed as long as we don't know
+ * which registers really need to be saved.
+ */
+ mfc0 k1, CP0_CONTEXT
+ dsra k1, 1
+ lwu k0, (k1) # May cause another exception
+ lwu k1, 4(k1)
+ dsrl k0, 6 # Convert to EntryLo format
+ dsrl k1, 6 # Convert to EntryLo format
+ dmtc0 k0, CP0_ENTRYLO0
+ dmtc0 k1, CP0_ENTRYLO1
+ nop # Needed for R4[04]00 pipeline
+ tlbwr
+ nop # Needed for R4[04]00 pipeline
+ nop
+ nop
+ eret
+ nop /* Workaround for R4000 bug. */
+ eret
+ END(except_vec1_generic)
+
+ /* Cache Error */
+ LEAF(except_vec2_generic)
+ /* Famous last words: unreached */
+ mfc0 a1,CP0_ERROREPC
+ PRINT("Cache error exception: c0_errorepc == %08x\n")
+1:
+ j 1b
+ nop
+ END(except_vec2_generic)
+
+ /* General exception vector R4000 version. */
+ NESTED(except_vec3_r4000, 0, sp)
+ .set noat
+ mfc0 k1, CP0_CAUSE
+
+ /* XXX Have to check for VCE's _before_ we do a load or store. */
+
+ la k0, exception_handlers
+ andi k1, k1, 0x7c
+ addu k0, k0, k1
+ lw k0, (k0)
+ nop
+ jr k0
+ nop
+ END(except_vec3_r4000)
+ .set at
+
+ /* General exception vector. */
+ NESTED(except_vec3_generic, 0, sp)
+ .set noat
+ mfc0 k1, CP0_CAUSE
+ la k0, exception_handlers
+ andi k1, k1, 0x7c
+ addu k0, k0, k1
+ lw k0, (k0)
+ nop
+ jr k0
+ nop
+ END(except_vec3_generic)
+ .set at
/*
- * Kernel entry
+ * Kernel entry point
*/
- .set noreorder
-
- NESTED(kernel_entry, 16, sp)
- /*
- * The following two symbols are used for kernel profiling.
- */
- EXPORT(stext)
- EXPORT(_stext)
-
- /*
- * Initialize the global pointer, if required.
- */
- LOAD_GP
-
- /*
- * First setup stack for kernel and init
- */
- la sp,init_user_stack+(KERNEL_STACK_SIZE-4*SZREG)
- la t0,init_kernel_stack+(KERNEL_STACK_SIZE)
- LONG_S t0,kernelsp
-
- /*
- * Clear BSS first so that there are no surprises...
- */
- la t0,_edata
- la t1,_end
- sb zero,(t0)
-1: addiu t0,1
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1)
- /*
- * Paul, this clears one word too much - Ralf
- */
- bne t0,t1,1b
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS4)
- bnel t0,t1,1b
-#endif
- sb zero,(t0) # delay slot
-
- /*
- * Get the memory upper limit the bootloader passed to us
- * in a0
- */
- sw a0,mips_memory_upper
-
- /*
- * Get the very one tags we need early in the boot process
- */
- jal bi_EarlySnarf
- nop
-
- /*
- * 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
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- nop
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- mtc0 zero,CP0_WIRED # delay slot
-#endif
- jal wire_mappings
- nop
-
- /*
- * Disable coprocessors
- */
- 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)
+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
-/*
- * wire_mappings - used to map hardware registers
- */
- LEAF(wire_mappings)
- /*
- * Get base address of map0 table for the
- * the board we're running on
- */
- lw t1,mips_machgroup # mips_machgroup is set by
- # bi_EarlySnarf()
- la t0,map0table
- sll t1,PTRLOG # machgroup used as index
- addu t0,t1
- lw t1,mips_machtype # mips_machtype is set by
- # bi_EarlySnarf()
- lw t0,(t0) # load table @ for the group
- sll t1,PTRLOG # machtype used as index
- addu t0,t1
- lw t0,(t0) # load table @ for the box
- 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
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- nop
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- mtc0 t3,CP0_WIRED # delay slot
-#endif
- addiu t0,8
-1: lw t4,24(t0) # PageMask
- ld t5,0(t0) # entryHi
- ld t6,8(t0) # entryLo0
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- ld t7,16(t0) # entryLo1
-#endif
- addiu t2,1 # increment ctr
- mtc0 t2,CP0_INDEX # set TLB entry
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- nop
- mtc0 t5,CP0_ENTRYHI
- nop
- mtc0 t6,CP0_ENTRYLO0
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- mtc0 t4,CP0_PAGEMASK
- dmtc0 t5,CP0_ENTRYHI
- dmtc0 t6,CP0_ENTRYLO0
- dmtc0 t7,CP0_ENTRYLO1
-#endif
- 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:
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- li t0,PM_4K
- mtc0 t0,CP0_PAGEMASK
+ jal wire_mappings_r3000
+ nop
+
+ /*
+ * Stack for kernel and init
+ */
+9: la sp, init_user_stack+(KERNEL_STACK_SIZE-4*SZREG)
+ la t0, init_kernel_stack+(KERNEL_STACK_SIZE)
+ sw t0, 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)
-#endif
- /*
- * Now map the pagetables
- */
- mtc0 zero,CP0_INDEX
- la t0,TLB_ROOT
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- mtc0 t0,CP0_ENTRYHI
- nop
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- dmtc0 t0,CP0_ENTRYHI
-#endif
- la t0,swapper_pg_dir-KSEG1
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- srl t0,12
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- srl t0,6
-#endif
- ori t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- mtc0 t0,CP0_ENTRYLO0
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- dmtc0 t0,CP0_ENTRYLO0
- li t0,MODE_GLOBAL
- dmtc0 t0,CP0_ENTRYLO1
-#endif
- 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
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- srl t0,1 # this is a guess!
- mtc0 t0,CP0_CONTEXT
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- dsll t0,1
- dmtc0 t0,CP0_CONTEXT
-#endif
- jr ra # delay slot
- nop
- END(wire_mappings)
+/*
+ * wire_mappings - used to map hardware registers, r4xx0 version.
+ */
+LEAF(wire_mappings_r4xx0)
+ mtc0 zero, CP0_WIRED
+ nop
+ nop
+ nop
+ j ra
+ nop
+ END(wire_mappings_r4xx0)
- .data
+/*
+ * R3000 version of wire_mappings.
+ */
+LEAF(wire_mappings_r3000)
+ /*
+ * Get base address of map0 table for the
+ * the board we're running on
+ */
+ lw t1, mips_machtype
+ la t0, map0table
+ sll t1, PTRLOG # machtype used as index
+ addu t0, t1
+ lw t0, (t0) # get base address
+ nop
+ /* Get number of wired TLB entries and
+ * loop over selected map0 table.
+ */
+ lw t1, (t0) # number of wired TLB entries
+ move t2, zero # TLB entry counter
+ addiu t3, t1, 1 # wire one additional entry
+ beqz t1, 2f # null, exit
+ nop
+
+ addiu t0, 8
+1:
+ lw t4, 24(t0) # PageMask
+ ld t5, 0(t0) # entryHi
+ ld t6, 8(t0) # entryLo0
+ addiu t2, 1 # increment ctr
+ mtc0 t2, CP0_INDEX # set TLB entry
+ nop
+ mtc0 t5, CP0_ENTRYHI
+ nop
+ mtc0 t6, CP0_ENTRYLO0
+ addiu t0, 32
+ bne t1, t2, 1b # next TLB entry
+ tlbwi
+
+ /* We use only 4k pages. Therefore the PageMask register
+ * is expected to be setup for 4k pages.
+ */
+2:
+ /* Now map the pagetables */
+ mtc0 zero, CP0_INDEX
+ la t0, TLB_ROOT
+ mtc0 t0, CP0_ENTRYHI
+ nop
+ la t0, swapper_pg_dir
+ srl t0, 12
+ ori t0, (0x00e0|0x0100) # uncachable, dirty, valid
+ mtc0 t0, CP0_ENTRYLO0
+ nop
+ tlbwi # delayed
+
+ /* Load the context register with zero. To see why, look
+ * at how the tlb refill code above works.
+ */
+ mtc0 zero, CP0_CONTEXT
+
+ jr ra
+ nop
+ END(wire_mappings_r3000)
+
+ /* CPU type probing code, called at Kernel entry. */
+ LEAF(cpu_probe)
+ mfc0 t0, CP0_PRID
+ la t3, mips_cputype
+ andi t1, t0, 0xff00
+ li t2, PRID_IMP_R2000
+ bne t1, t2, 1f
+ andi t0, 0x00ff
+
+ li t2, CPU_R2000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R3000
+ bne t1, t2, 1f
+ nop
+
+ li t2, PRID_REV_R3000A
+ bne t0, t2, 9f
+ nop
+
+ li t2, CPU_R3000A
+ b probe_done
+ sw t2, (t3)
+9:
+ li t2, CPU_R3000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R6000
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R6000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R4000
+ bne t1, t2, 1f
+ nop
+
+ li t2, PRID_REV_R4400
+ bne t0, t2, 9f
+ nop
+
+ li t2, CPU_R4400SC
+ b probe_done
+ sw t2, (t3)
+9:
+ li t2, CPU_R4000SC
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R6000A
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R6000A
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R10000
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R10000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R8000
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R8000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R4600
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R4600
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R4700
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R4700
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R4650
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R4650
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, PRID_IMP_R5000
+ bne t1, t2, 1f
+ nop
+
+ li t2, CPU_R5000
+ b probe_done
+ sw t2, (t3)
+1:
+ li t2, CPU_UNKNOWN
+ sw t2, (t3)
+
+ b probe_done
+ nop
+ END(cpu_probe)
+
+ .data
/*
* Build an entry for table of wired entries
*/
@@ -465,42 +647,17 @@ EXPORT(end_except)
* Add your own stuff here but don't forget to define your
* target system in bootinfo.h
*/
-/* First indirection level on the 'group' */
-map0table: PTR map0table_unknown # machgroup = unknown
- PTR map0table_jazz # machgroup = JAZZ
- PTR map0table_dec # machgroup = DEC
- PTR map0table_arc # machgroup = ARC
- PTR map0table_sni_rm # machgroup = SNI_RM
- PTR map0table_acn # machgroup = ACN
- .word 0 # pad
-
-/* table for group 'unknown' */
-map0table_unknown: PTR map0_dummy # machtype = unknown
- .word 0 # pad
-
-/* table for group 'Jazz' */
-map0table_jazz: PTR map0_pica61 # Acer Pica-61
- PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030)
- PTR map0_magnum4000 # Olivetti M700 (*same* table)
- .word 0 # pad
-
-/* table for group 'Dec' */
-map0table_dec: PTR map0_dummy # DEC Personal DECStation 5000/2x (for now)
- .word 0 # pad
-/* table for group 'ARC' */
-map0table_arc: PTR map0_rpc # Deskstation rPC44
+map0table: PTR map0_dummy # machtype = unknown
+ PTR map0_rpc # Deskstation rPC44
PTR map0_tyne # Deskstation Tyne
+ PTR map0_pica61 # Acer Pica-61
+ PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030)
+ 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
-/* table for group 'SNI_RM' */
-map0table_sni_rm: PTR map0_sni_rm200_pci # SNI RM200 PCI
- .word 0
-
-/* table for group 'ACN' */
-map0table_acn: PTR map0_dummy # ACN mips board
- .word 0
-
-/* dummy table */
map0_dummy: .word 0 # 0 entries
.align 3
@@ -513,8 +670,8 @@ map0_dummy: .word 0 # 0 entries
map0_rpc: .word 2 # no. of wired TLB entries
.word 0 # pad for alignment
-MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000011, PM_16M) # ISA Memory space
-MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000011, PM_64K) # ISA I/O 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.
@@ -522,18 +679,23 @@ MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000011, PM_64K) # ISA I/O Space
map0_tyne: .word 2 # no. of wired TLB entries
.word 0 # pad for alignment
-MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000011, PM_1M) # VESA DMA cache
+MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache
MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space
/*
* Initial mapping for ACER PICA-61 boards.
+ * FIXME: These are rather preliminary since many drivers, such as serial,
+ * parallel, scsi and ethernet need some changes to distinguish between "local"
+ * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped
+ * to the same location as the bios maps it to. Console driver has been changed
+ * accordingly (new video type: VIDEO_TYPE_PICA_S3).
* FIXME: Remove or merge some of the mappings.
*/
map0_pica61: .word 7 # no. wired TLB entries
.word 0 # dummy
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000011, PM_64K) # Local I/O space
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000011, PM_4K) # Interrupt source register
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # Local I/O space
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # Interrupt source register
MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # Local video control
MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # Extended video control
MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # Local video memory (BIOS mapping)
@@ -542,15 +704,16 @@ MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # PCR (???)
/*
* Initial mapping for Mips Magnum 4000PC systems.
+ * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
* FIXME: Remove or merge some of the mappings.
*/
map0_magnum4000:
.word 8 # no. wired TLB entries
.word 0 # dummy
-MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000011, PM_256K) # 0
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000011, PM_64K) # 1 local I/O
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000011, PM_4K) # 2 IRQ source
+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.
@@ -567,8 +730,7 @@ map0_sni_rm200_pci:
.text
.org 0x1000
- .globl swapper_pg_dir
-swapper_pg_dir = . + (KSEG1-KSEG0)
+ EXPORT(swapper_pg_dir)
.org 0x2000
EXPORT(empty_bad_page)
diff --git a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c
index 336965acf..a68a91c21 100644
--- a/arch/mips/kernel/ipc.c
+++ b/arch/mips/kernel/ipc.c
@@ -5,7 +5,6 @@
* 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>
@@ -13,6 +12,9 @@
#include <linux/msg.h>
#include <linux/shm.h>
+#include <asm/ipc.h>
+#include <asm/uaccess.h>
+
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
@@ -20,7 +22,6 @@
*/
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
-#ifdef CONFIG_SYSVIPC
int version;
version = call >> 16; /* hack for backward compatibility */
@@ -39,7 +40,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err;
- get_from_user(fourth.__pad, ptr);
+ get_user(fourth.__pad, (void **) ptr);
return sys_semctl (first, second, third, fourth);
}
default:
@@ -59,8 +60,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
return err;
- memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
- sizeof (tmp));
+ copy_from_user(&tmp,(struct ipc_kludge *) ptr, sizeof (tmp));
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
}
case 1: default:
@@ -103,7 +103,4 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
return -EINVAL;
}
return -EINVAL;
-#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
index 000000000..a20e619e3
--- /dev/null
+++ b/arch/mips/kernel/irix5sys.h
@@ -0,0 +1,1024 @@
+/* $Id: irix5sys.h,v 1.8 1996/07/09 08:24:17 dm 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(irix_poll, 3) /* 1087 sys_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
index 000000000..ec4f5c449
--- /dev/null
+++ b/arch/mips/kernel/irixelf.c
@@ -0,0 +1,1374 @@
+/* $Id: irixelf.c,v 1.8 1996/08/24 03:52:25 dm Exp $
+ * 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/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/segment.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, &mod_use_count_, 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;
+ char * fpnt;
+
+ nbyte = elf_bss & (PAGE_SIZE-1);
+ if (nbyte) {
+ nbyte = PAGE_SIZE - nbyte;
+ /* FIXME: someone should investigate, why a bad binary
+ * is allowed to bring a wrong elf_bss until here,
+ * and how to react. Suffice the plain return?
+ * rossius@hrz.tu-chemnitz.de
+ */
+ if (verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte))
+ return;
+
+ fpnt = (char *) elf_bss;
+ do {
+ put_user(0, fpnt++);
+ } while (--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)
+{
+ unsigned long *argv,*envp, *dlinfo;
+ 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;
+ dlinfo = sp;
+ sp -= envc+1;
+ envp = sp;
+ sp -= argc+1;
+ argv = sp;
+
+ put_user((unsigned long)argc, --sp);
+
+#define NEW_AUX_ENT(id, val) \
+ put_user ((id), dlinfo++); \
+ put_user ((val), dlinfo++)
+
+#define INTERP_ALIGN (~((64 * 1024) - 1))
+
+ if(exec) {
+ struct elf_phdr * eppnt;
+ eppnt = (struct elf_phdr *) exec->e_phoff;
+
+ /* Put this here for an ELF program interpreter */
+ NEW_AUX_ENT (AT_PHDR, ephdr->p_vaddr);
+ NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
+ NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
+ NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
+ NEW_AUX_ENT (AT_BASE, (interp_load_addr & (INTERP_ALIGN)));
+ NEW_AUX_ENT (AT_FLAGS, 0);
+ NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
+ NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
+ NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
+ NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
+ NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
+ }
+ NEW_AUX_ENT (AT_NULL, 0);
+#undef NEW_AUX_ENT
+
+ current->mm->arg_start = (unsigned long) p;
+ while (argc-->0) {
+ put_user(p,argv++);
+ while (get_user(p++)) /* nothing */ ;
+ }
+ put_user(0,argv);
+ current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+ while (envc-->0) {
+ put_user(p,envp++);
+ while (get_user(p++)) /* nothing */ ;
+ }
+ put_user(0,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) ||
+ INCOMPATIBLE_MACHINE(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) ||
+ INCOMPATIBLE_MACHINE(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->use_count)
+ (*current->exec_domain->use_count)--;
+ if (current->binfmt && current->binfmt->use_count)
+ (*current->binfmt->use_count)--;
+ current->exec_domain = lookup_exec_domain(current->personality);
+ current->binfmt = &irix_format;
+ if (current->exec_domain && current->exec_domain->use_count)
+ (*current->exec_domain->use_count)++;
+ if (current->binfmt && current->binfmt->use_count)
+ (*current->binfmt->use_count)++;
+
+ 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->lseek) {
+ if ((error = file->f_op->lseek(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 ||
+ INCOMPATIBLE_MACHINE(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->lseek) {
+ if (file->f_op->lseek(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_EM_CPU;
+ 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;
+ copy_sigbits32(&prstatus.pr_sigpend, current->signal);
+ copy_sigbits32(&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->utime);
+ prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime);
+ prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime);
+ prstatus.pr_stime.tv_usec = CT_TO_USECS(current->stime);
+ prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->cutime);
+ prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime);
+ prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime);
+ prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->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;
+ memcpy_fromfs(&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;
+}
+
+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
index 000000000..a8498084b
--- /dev/null
+++ b/arch/mips/kernel/irixioctl.c
@@ -0,0 +1,254 @@
+/* $Id: irixioctl.c,v 1.4 1996/07/14 09:36:16 dm 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/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)
+{
+ unsigned long *data;
+ struct tty_struct *tp, *rtp;
+ int error = 0;
+ int old_fs;
+
+#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
+ return error;
+}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
new file mode 100644
index 000000000..94f8004f6
--- /dev/null
+++ b/arch/mips/kernel/irixsig.c
@@ -0,0 +1,826 @@
+/* $Id: irixsig.c,v 1.5 1996/08/05 09:20:56 dm 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/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)))
+ do_exit(SIGSEGV);
+
+ __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;
+}
+
+extern asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+
+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_waitpid(-1,NULL,WNOHANG) > 0)
+ /* nothing */;
+ continue;
+ }
+ if (sa->sa_handler == SIG_DFL) {
+ if (current->pid == 1)
+ continue;
+ switch (signr) {
+ case SIGCONT: case SIGCHLD: case SIGWINCH:
+ continue;
+
+ case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ 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:
+ if (current->binfmt && current->binfmt->core_dump) {
+ if (current->binfmt->core_dump(signr, regs))
+ signr |= 0x80;
+ }
+ /* fall through */
+ default:
+ current->signal |= _S(signr & 0x7f);
+ current->flags |= PF_SIGNALED;
+ do_exit(signr);
+ }
+ }
+ /*
+ * 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 &= ~*to_k_sigset_t(&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 |= *to_k_sigset_t(&sa->sa_mask);
+ oldmask |= *to_k_sigset_t(&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:
+ do_exit(SIGSEGV);
+}
+
+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;
+ if (p->sa_handler == SIG_IGN) {
+ current->signal &= ~_S(signum);
+ return;
+ }
+ if (p->sa_handler == SIG_DFL) {
+ if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
+ return;
+ current->signal &= ~_S(signum);
+ return;
+ }
+}
+
+asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
+ struct sigact_irix5 *old, unsigned long trampoline)
+{
+ struct sigaction new_sa, *p;
+
+#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) {
+ int err = verify_area(VERIFY_READ, new, sizeof(*new));
+ if(err)
+ return err;
+ if(sig == SIGKILL || sig == SIGSTOP)
+ return -EINVAL;
+ new_sa.sa_flags = new->flags;
+ new_sa.sa_handler = (__sighandler_t) new->handler;
+ new_sa.sa_mask.__sigbits[1] = new_sa.sa_mask.__sigbits[2] =
+ new_sa.sa_mask.__sigbits[3] = 0;
+ new_sa.sa_mask.__sigbits[0] = new->sigset[0];
+
+ if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
+ err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
+ if(err)
+ return err;
+ }
+ }
+ /* 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 err = verify_area(VERIFY_WRITE, old, sizeof(*old));
+ if(err)
+ return err;
+ old->flags = p->sa_flags;
+ old->handler = (void *) p->sa_handler;
+ old->sigset[1] = old->sigset[2] = old->sigset[3] = 0;
+ old->sigset[0] = p->sa_mask.__sigbits[0];
+ old->_unused0[0] = old->_unused0[1] = 0;
+ }
+
+ if(new) {
+ *p = new_sa;
+ check_pending(sig);
+ }
+
+ return 0;
+}
+
+asmlinkage int irix_sigpending(unsigned long *set)
+{
+ int err;
+
+ err = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4));
+ if(!err) {
+ set[1] = set[2] = set[3] = 0;
+ set[0] = (current->blocked & current->signal);
+ }
+ return err;
+}
+
+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;
+ old[1] = old[2] = old[3] = 0;
+ old[0] = oldbits;
+ }
+ return 0;
+}
+
+asmlinkage int irix_sigsuspend(struct pt_regs *regs)
+{
+ unsigned int mask;
+ unsigned long *uset;
+ int base = 0;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+
+ mask = current->blocked;
+ uset = (unsigned long *) regs->regs[base + 4];
+ if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4)))
+ return -EFAULT;
+ current->blocked = uset[0] & _BLOCKABLE;
+ while(1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if(do_irix_signal(mask, regs))
+ return -EINTR;
+ }
+}
+
+/* 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;
+
+#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;
+ kset = set[0];
+
+ error = verify_area(VERIFY_READ, set, (sizeof(unsigned long) * 4));
+ if(error)
+ return error;
+
+ if(info) {
+ error = verify_area(VERIFY_WRITE, info, sizeof(*info));
+ if(error)
+ return error;
+ memset(info, 0, sizeof(*info));
+ }
+
+ if(tp) {
+ error = verify_area(VERIFY_READ, tp, sizeof(*tp));
+ if(error)
+ return error;
+ if(!tp->tv_sec && !tp->tv_nsec)
+ return -EINVAL;
+ 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;
+ return 0;
+ }
+ }
+
+ /* Should not get here, but do something sane if we do. */
+ return -EINTR;
+}
+
+/* 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;
+
+ if(!info)
+ return -EINVAL;
+ flag = verify_area(VERIFY_WRITE, info, sizeof(*info));
+ if(flag)
+ return flag;
+ if(ru) {
+ flag = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
+ if(flag)
+ return flag;
+ }
+ if(options & ~(W_MASK))
+ return -EINVAL;
+ if(type != P_PID && type != P_PGID && type != P_ALL)
+ return -EINVAL;
+ 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);
+ info->sig = SIGCHLD;
+ info->code = 0;
+ info->stuff.procinfo.pid = p->pid;
+ info->stuff.procinfo.procdata.child.status =
+ (p->exit_code >> 8) & 0xff;
+ info->stuff.procinfo.procdata.child.utime =
+ p->utime;
+ info->stuff.procinfo.procdata.child.stime =
+ p->stime;
+ p->exit_code = 0;
+ retval = 0;
+ goto end_waitsys;
+ case TASK_ZOMBIE:
+ current->cutime += p->utime + p->cutime;
+ current->cstime += p->stime + p->cstime;
+ if (ru != NULL)
+ getrusage(p, RUSAGE_BOTH, ru);
+ info->sig = SIGCHLD;
+ info->code = 1; /* CLD_EXITED */
+ info->stuff.procinfo.pid = p->pid;
+ info->stuff.procinfo.procdata.child.status =
+ (p->exit_code >> 8) & 0xff;
+ info->stuff.procinfo.procdata.child.utime =
+ p->utime;
+ info->stuff.procinfo.procdata.child.stime =
+ p->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);
+ 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;
+
+ 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)
+ return error;
+ 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");
+ }
+ return 0;
+}
+
+asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
+{
+ int error, base = 0;
+ struct irix5_context *ctx;
+
+ 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)
+ return error;
+
+ 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;
+ return regs->regs[2];
+}
+
+struct irix_sigstack { unsigned long sp; int status; };
+
+asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
+{
+ int error;
+
+#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)
+ return error;
+ }
+
+ if(old) {
+ error = verify_area(VERIFY_WRITE, old, sizeof(*old));
+ if(error)
+ return error;
+ }
+ return 0;
+}
+
+struct irix_sigaltstack { unsigned long sp; int size; int status; };
+
+asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
+ struct irix_sigaltstack *old)
+{
+ int error;
+
+#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)
+ return error;
+ }
+
+ if(old) {
+ error = verify_area(VERIFY_WRITE, old, sizeof(*old));
+ if(error)
+ return error;
+ }
+ return 0;
+}
+
+struct irix_procset {
+ int cmd, ltype, lid, rtype, rid;
+};
+
+asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
+{
+ int error;
+
+ error = verify_area(VERIFY_READ, pset, sizeof(*pset));
+#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
+
+ return -EINVAL;
+}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index a6f257c88..2192112e9 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -11,6 +11,7 @@
*
* Mips support by Ralf Baechle and Andreas Busse
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
@@ -30,6 +31,9 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/vector.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
unsigned char cache_21 = 0xff;
unsigned char cache_A1 = 0xff;
@@ -88,10 +92,9 @@ void enable_irq(unsigned int irq_nr)
}
/*
- * Low-level interrupt handlers: first the timer interrupt, then the
- * general, then the fast and finally the bad interrupt handler.
+ * Pointers to the low-level handlers: first the general ones, then the
+ * fast ones, then the bad ones.
*/
-extern void timer_interrupt(void);
extern void interrupt(void);
extern void fast_interrupt(void);
extern void bad_interrupt(void);
@@ -112,7 +115,7 @@ int get_irq_list(char *buf)
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8u %c %s",
+ len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
@@ -136,16 +139,18 @@ 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 = 0;
-
kstat.interrupts[irq]++;
+#ifdef CONFIG_SGI
+ prom_printf("Got irq %d, press a key.", irq);
+ prom_getchar();
+ romvec->imode();
+#endif
while (action) {
- do_random |= action->flags;
+ if (action->flags & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
action->handler(irq, action->dev_id, regs);
action = action->next;
}
- if (do_random & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
}
/*
@@ -156,16 +161,14 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
asmlinkage void do_fast_IRQ(int irq)
{
struct irqaction * action = *(irq + irq_action);
- int do_random = 0;
kstat.interrupts[irq]++;
while (action) {
- do_random |= action->flags;
+ if (action->flags & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
action->handler(irq, action->dev_id, NULL);
action = action->next;
}
- if (do_random & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
}
/*
@@ -209,10 +212,7 @@ int setup_x86_irq(int irq, struct irqaction * new)
if (new->flags & SA_INTERRUPT)
set_int_vector(irq,fast_interrupt);
else
- if (irq == 0)
- set_int_vector(irq,timer_interrupt);
- else
- set_int_vector(irq,interrupt);
+ set_int_vector(irq,interrupt);
unmask_irq(irq);
}
restore_flags(flags);
@@ -307,7 +307,7 @@ int probe_irq_off (unsigned long irqs)
irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
#ifdef DEBUG
- printk("probe_irq_off: irqs=0x%04lx irqmask=0x%04x\n", irqs, irqmask);
+ printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
#endif
irqs &= irqmask;
if (!irqs)
diff --git a/arch/mips/kernel/ksyms.c b/arch/mips/kernel/ksyms.c
index c80bf588a..28650741e 100644
--- a/arch/mips/kernel/ksyms.c
+++ b/arch/mips/kernel/ksyms.c
@@ -8,8 +8,8 @@
* Copyright (C) 1996 by Ralf Baechle
*/
#include <linux/module.h>
+#include <linux/string.h>
#include <linux/mm.h>
-#include <asm/cache.h>
#include <asm/dma.h>
#include <asm/floppy.h>
#include <asm/io.h>
@@ -20,12 +20,13 @@ static struct symbol_table arch_symbol_table = {
/*
* String functions
*/
- X(__generic_memset_b),
- X(__generic_memset_dw),
+ X(memset),
+ X(memcpy),
+ X(memmove),
+ X(bcopy),
/*
* Functions to control caches.
*/
- X(cacheflush),
X(fd_cacheflush),
/*
* Base address of ports for Intel style I/O.
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 2ce906ea4..99e3a3075 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -9,6 +9,7 @@
* 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>
@@ -23,42 +24,47 @@
#include <linux/a.out.h>
#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/uaccess.h>
+#include <asm/segment.h>
#include <asm/pgtable.h>
-#include <asm/sgidefs.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
+
+int active_ds = USER_DS;
asmlinkage void ret_from_sys_call(void);
/*
- * Free current thread data structures etc..
+ * Do necessary setup to start up a newly executed thread.
*/
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+{
+ /* 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;
+}
+
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
- */
}
-
+
void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
@@ -66,80 +72,66 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
long childksp;
childksp = p->kernel_stack_page + KERNEL_STACK_SIZE - 8;
- /*
- * set up new TSS
- */
+
+ /* set up new TSS. */
childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
*childregs = *regs;
- childregs->regs[2] = (__register_t) 0; /* Child gets zero as return value */
- childregs->regs[7] = (__register_t) 0; /* Clear error flag */
- regs->regs[2] = (__register_t) p->pid;
- if (childregs->cp0_status & ST0_CU0)
- childregs->regs[29] = (__register_t) childksp;
- else
- childregs->regs[29] = (__register_t) 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 = (__register_t)(long) childregs; /* new sp */
- p->tss.reg31 = (__register_t) ret_from_sys_call;
-
- /*
- * Copy thread specific flags.
- */
- p->tss.mflags = p->tss.mflags;
+ p->tss.reg29 = (unsigned long) childregs;
+ p->tss.reg31 = (unsigned long) ret_from_sys_call;
/*
* New tasks loose permission to use the fpu. This accelerates context
* switching for most programs since they don't use the fpu.
*/
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
- ~(ST0_CU3|ST0_CU2|ST0_CU1);
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
- ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
-#endif
+ ~(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;
}
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-extern void (*switch_to_user_mode)(struct pt_regs *regs);
-
-void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
-{
- set_fs(USER_DS);
- regs->cp0_epc = (__register_t) pc;
- /*
- * New thread loses kernel privileges.
- */
- switch_to_user_mode(regs);
- regs->regs[29] = (__register_t) sp;
- regs->regs[31] = 0;
-}
-
-/*
- * fill in the fpu structure for a core dump..
- *
- * Actually this is "int dump_fpu (struct pt_regs * regs, struct user *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));
}
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 93fae9961..018b68023 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -1,12 +1,8 @@
-/*
- * Ptrace(2) syscall for MIPS. Based on arch/i386/kernel/ptrace.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
- * for more details.
- *
- * Copyright (C) 1995, 1996 by Ralf Baechle.
- */
+/* ptrace.c */
+/* By Ross Biro 1/23/92 */
+/* edited by Linus Torvalds */
+/* further hacked for MIPS by David S. Miller (dm@engr.sgi.com) */
+
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -17,26 +13,11 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/page.h>
#include <asm/system.h>
-/*
- * 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
-
-/*
- * this is the number to subtract from the top of the stack. To find
- * the local frame.
- */
-#define MAGICNUMBER 68
-
/* change a pid into a task struct. */
-static inline struct task_struct *
-get_task(int pid)
+static inline struct task_struct * get_task(int pid)
{
int i;
@@ -48,51 +29,18 @@ get_task(int pid)
}
/*
- * 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.
- */
-static inline int
-get_stack_long(struct task_struct *task, int offset)
-{
- unsigned char *stack;
-
- stack = (unsigned char *)(unsigned long)task->tss.reg29;
- 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 *)(unsigned long)task->tss.reg29;
- 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 task_struct * tsk,
- 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;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- unsigned long page;
+ pgd_t *pgdir;
+ pmd_t *pgmiddle;
+ pte_t *pgtable;
+ unsigned long page, retval;
repeat:
pgdir = pgd_offset(vma->vm_mm, addr);
@@ -120,11 +68,14 @@ repeat:
do_no_page(tsk, vma, addr, 0);
goto repeat;
}
+ page = pte_page(*pgtable);
/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) < max_mapnr)
+ 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;
}
/*
@@ -136,9 +87,9 @@ 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 task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr, unsigned long data)
+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;
@@ -176,22 +127,19 @@ repeat:
do_wp_page(tsk, vma, addr, 1);
goto repeat;
}
- /*
- * This is a hack for non-kernel-mapped video buffers and similar
- */
- if (page >= high_memory)
+/* this is a hack for non-kernel-mapped video buffers and similar */
+ flush_cache_page(vma, addr);
+ if (MAP_NR(page) < MAP_NR(high_memory)) {
*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
- /*
- * We're bypassing pagetables, so we have to set the dirty bit
- * ourselves. This should also re-instate whatever read-only mode
- * there was before
- */
+ 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)));
- flush_tlb();
+ flush_tlb_page(vma, addr);
}
-static struct vm_area_struct *
-find_extend_vma(struct task_struct * tsk, unsigned long addr)
+static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
{
struct vm_area_struct * vma;
@@ -214,9 +162,8 @@ find_extend_vma(struct task_struct * tsk, unsigned long addr)
* This routine checks the page boundaries, and that the offset is
* within the task area. It then calls get_long() to read a long.
*/
-static int
-read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
+static int read_long(struct task_struct * tsk, unsigned long addr,
+ unsigned long * result)
{
struct vm_area_struct * vma = find_extend_vma(tsk, addr);
@@ -257,9 +204,8 @@ read_long(struct task_struct * tsk, unsigned long addr,
* This routine checks the page boundaries, and that the offset is
* within the task area. It then calls put_long() to write a long.
*/
-static int
-write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
+static int write_long(struct task_struct * tsk, unsigned long addr,
+ unsigned long data)
{
struct vm_area_struct * vma = find_extend_vma(tsk, addr);
@@ -306,14 +252,15 @@ write_long(struct task_struct * tsk, unsigned long addr,
return 0;
}
-asmlinkage int
-sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- struct user * dummy;
-
- dummy = NULL;
+#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)
@@ -334,7 +281,7 @@ sys_ptrace(long request, long pid, long addr, long data)
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
- (current->gid != child->sgid) ||
+ (current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
/* the same process cannot be attached many times */
@@ -359,6 +306,7 @@ sys_ptrace(long request, long pid, long addr, long data)
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;
@@ -369,83 +317,114 @@ sys_ptrace(long request, long pid, long addr, long data)
return res;
res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
if (!res)
- put_user(tmp, (unsigned long *)data);
+ put_user(tmp,(unsigned long *) data);
return res;
}
-#if 0
- /*
- * Read the word at location addr in the USER area.
- */
+ /* 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 < 0 || addr > sizeof(struct user) - 3)
- return -EIO;
-
- 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;
+ regs = (struct pt_regs *)
+ (child->tss.ksp - sizeof(struct pt_regs));
+ res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
+ if(res < 0)
+ return res;
+ res = 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;
+ break;
+ };
}
- put_user(tmp, (unsigned long *)data);
- return 0;
+ if(!res)
+ put_user(tmp, (unsigned long *) data);
+ return res;
}
-#endif
- /*
- * Write the word at location addr.
- */
- case PTRACE_POKETEXT:
+
+ /* 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);
- /*
- * Write the word at location addr in the user area.
- */
- case PTRACE_POKEUSR:
-#if 0
- 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;
+ 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;
- }
-
- return -EIO;
-#endif
+ return res;
+ }
- /*
- * Continue and stop at next (return from) syscall.
- */
- case PTRACE_SYSCALL:
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
- if ((unsigned long) data > _NSIG)
+ if ((unsigned long) data > NSIG)
return -EIO;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
@@ -453,35 +432,19 @@ sys_ptrace(long request, long pid, long addr, long data)
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
wake_up_process(child);
- return 0;
+ return data;
}
- /*
- * Make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
+/*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
case PTRACE_KILL: {
- if (child->state == TASK_ZOMBIE) /* already dead */
- return 0;
- wake_up_process(child);
- child->exit_code = SIGKILL;
- return 0;
- }
-
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
- /*
- * Not supported yet.
- */
- return -ENOSYS;
-
- if ((unsigned long) data > NSIG)
- return -EIO;
- wake_up_process(child);
- child->exit_code = data;
- /*
- * give it a chance to run.
- */
+ if (child->state != TASK_ZOMBIE) {
+ wake_up_process(child);
+ child->exit_code = SIGKILL;
+ }
return 0;
}
@@ -502,8 +465,7 @@ sys_ptrace(long request, long pid, long addr, long data)
}
}
-asmlinkage void
-syscall_trace(void)
+asmlinkage void syscall_trace(void)
{
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
new file mode 100644
index 000000000..666a9a180
--- /dev/null
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -0,0 +1,139 @@
+/* $Id: r2300_fpu.S,v 1.1 1996/06/24 06:35:26 dm 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>
+
+ .text
+ .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
index 000000000..0afdab4c9
--- /dev/null
+++ b/arch/mips/kernel/r2300_misc.S
@@ -0,0 +1,398 @@
+/* $Id: r2300_misc.S,v 1.2 1996/06/29 12:41:08 dm 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/segment.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
index 000000000..358f46664
--- /dev/null
+++ b/arch/mips/kernel/r2300_scall.S
@@ -0,0 +1,86 @@
+/* $Id: r2300_scall.S,v 1.3 1996/06/29 12:41:08 dm 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/segment.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
+ .text
+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
+ .text
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
new file mode 100644
index 000000000..db03636d1
--- /dev/null
+++ b/arch/mips/kernel/r2300_switch.S
@@ -0,0 +1,102 @@
+/* $Id: r2300_switch.S,v 1.3 1996/06/29 07:06:42 dm 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/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/segment.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)
+ lui t5, %hi(current_set)
+ lw t0, %lo(current_set)(t5)
+ 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:
+ sw a0,%lo(current_set)(t5) # Switch current task
+ 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
index 000000000..6163b06a1
--- /dev/null
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -0,0 +1,148 @@
+/* $Id: r4k_fpu.S,v 1.3 1996/07/27 09:41:18 dm 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
index 000000000..510f513aa
--- /dev/null
+++ b/arch/mips/kernel/r4k_misc.S
@@ -0,0 +1,190 @@
+/* $Id: r4k_misc.S,v 1.8 1996/07/22 22:32:52 dm 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/offset.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/segment.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; \
+ lui ptr, %hi(current_set); \
+ srl pte, pte, 22; \
+ lw ptr, %lo(current_set)(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);
+
+ .text
+ .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
index 000000000..d4dd88732
--- /dev/null
+++ b/arch/mips/kernel/r4k_scall.S
@@ -0,0 +1,74 @@
+/* $Id: r4k_scall.S,v 1.4 1996/06/29 12:41:09 dm 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/segment.h>
+#include <asm/stackframe.h>
+
+ .text
+ .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
+ .text
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
new file mode 100644
index 000000000..22cd96fce
--- /dev/null
+++ b/arch/mips/kernel/r4k_switch.S
@@ -0,0 +1,71 @@
+/* $Id: r4k_switch.S,v 1.8 1996/07/10 01:24:20 dm Exp $
+ * 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/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/segment.h>
+#include <asm/stackframe.h>
+
+#include <asm/asmmacro.h>
+
+ .text
+ .set noreorder
+ .set mips3
+ .align 5
+ LEAF(r4xx0_resume)
+ lui t5, %hi(current_set)
+ lw t0, %lo(current_set)(t5)
+ 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:
+ sw a0, %lo(current_set)(t5)
+ 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/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
new file mode 100644
index 000000000..2d06f235f
--- /dev/null
+++ b/arch/mips/kernel/r6000_fpu.S
@@ -0,0 +1,100 @@
+/* $Id: r6000_fpu.S,v 1.1 1996/06/24 06:35:28 dm 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/setup.c b/arch/mips/kernel/setup.c
index 30304abda..48de5d21a 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -26,12 +26,15 @@
#include <asm/asm.h>
#include <asm/bootinfo.h>
-#include <asm/cache.h>
+#include <asm/cachectl.h>
#include <asm/io.h>
#include <asm/vector.h>
-#include <asm/uaccess.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
@@ -83,11 +86,12 @@ struct screen_info screen_info = DEFAULT_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; /* this is set by bi_EarlySnarf() */
-unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; /* this is set by bi_EarlySnarf() */
-unsigned long mips_tlb_entries = 48; /* this is set by bi_EarlySnarf() */
+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 root_mountflags;
extern int _end;
@@ -97,7 +101,12 @@ extern char empty_zero_page[PAGE_SIZE];
* This is set up by the setup-routine at boot-time
*/
#define PARAM empty_zero_page
+#if 0
+#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))
@@ -110,6 +119,12 @@ static char command_line[CL_SIZE] = { 0, };
*/
void (*irq_setup)(void);
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
+ * for the processor.
+ */
+unsigned long isa_slot_offset;
+
static void default_irq_setup(void)
{
panic("Unknown machtype in init_IRQ");
@@ -119,69 +134,6 @@ static void default_fd_cacheflush(const void *addr, size_t size)
{
}
-static asmlinkage void
-default_cacheflush(unsigned long addr, unsigned long nbytes, unsigned int flags)
-{
- /*
- * Someone didn't set his cacheflush() handler ...
- */
- panic("default_cacheflush() called.\n");
-}
-asmlinkage void (*cacheflush)(unsigned long addr, unsigned long nbytes, unsigned int flags) = default_cacheflush;
-
-static __inline__ void
-cpu_init(void)
-{
- asmlinkage void handle_reserved(void);
- void mips1_cpu_init(void);
- void mips2_cpu_init(void);
- void mips3_cpu_init(void);
- void mips4_cpu_init(void);
- int i;
-
- /*
- * Setup default vectors
- */
- for (i=0;i<=31;i++)
- set_except_vector(i, handle_reserved);
-
- switch(mips_cputype) {
-#ifdef CONFIG_CPU_R3000
- case CPU_R2000: case CPU_R3000: case CPU_R3000A: case CPU_R3041:
- case CPU_R3051: case CPU_R3052: case CPU_R3081: case CPU_R3081E:
- mips1_cpu_init();
- break;
-#endif
-#ifdef CONFIG_CPU_R6000
- case CPU_R6000: case CPU_R6000A:
- mips2_cpu_init();
- break;
-#endif
-#ifdef CONFIG_CPU_R4X00
- case CPU_R4000MC: case CPU_R4400MC: case CPU_R4000SC:
- case CPU_R4400SC: case CPU_R4000PC: case CPU_R4400PC:
- case CPU_R4200: case CPU_R4300: /* case CPU_R4640: */
- case CPU_R4600: case CPU_R4700:
- mips3_cpu_init();
- break;
-#endif
-#ifdef CONFIG_CPU_R8000
- case CPU_R8000: case CPU_R5000:
- printk("Detected unsupported CPU type %s.\n",
- cpu_names[mips_cputype]);
- panic("Can't handle CPU");
- break;
-#endif
-#ifdef CONFIG_CPU_R10000
- case CPU_R10000:
- mips4_cpu_init();
-#endif
- case CPU_UNKNOWN:
- default:
- panic("Unknown or unsupported CPU type");
- }
-}
-
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
@@ -191,14 +143,16 @@ void setup_arch(char **cmdline_p,
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_cputype);
- memcpy(&mips_cputype, TAGVALPTR(atag), atag->size);
+ atag = bi_TagFind(tag_machtype);
+ memcpy(&mips_machtype, TAGVALPTR(atag), atag->size);
- cpu_init();
+ 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);
@@ -226,6 +180,11 @@ void setup_arch(char **cmdline_p,
jazz_setup();
break;
#endif
+#ifdef CONFIG_SGI
+ case MACH_GROUP_SGI:
+ sgi_setup();
+ break;
+#endif
#ifdef CONFIG_SNI_RM200_PCI
case MACH_GROUP_SNI_RM:
sni_rm200_pci_setup();
@@ -237,6 +196,9 @@ void setup_arch(char **cmdline_p,
atag = bi_TagFind(tag_drive_info);
memcpy(&drive_info, TAGVALPTR(atag), atag->size);
+#if 0
+ aux_device_present = AUX_DEVICE_INFO;
+#endif
memory_end = mips_memory_upper;
/*
@@ -245,7 +207,7 @@ void setup_arch(char **cmdline_p,
* of one cache line at the end of memory unused to make shure we
* don't catch this type of bus errors.
*/
- memory_end -= 32;
+ memory_end -= 128;
memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
@@ -253,23 +215,14 @@ void setup_arch(char **cmdline_p,
rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
-#ifdef CONFIG_MAX_16M
- /*
- * There is a quite large number of different PC chipset based boards
- * available and so I include this option here just in case ...
- */
- if (memory_end > PAGE_OFFSET + 16*1024*1024)
- memory_end = PAGE_OFFSET + 16*1024*1024;
-#endif
- atag= bi_TagFind(tag_screen_info);
+ atag = bi_TagFind(tag_mount_root_rdonly);
if (atag)
- memcpy(&screen_info, TAGVALPTR(atag), atag->size);
+ root_mountflags |= MS_RDONLY;
atag = bi_TagFind(tag_command_line);
if (atag)
- memcpy(&command_line, TAGVALPTR(atag), atag->size);
- printk("Command line: '%s'\n", command_line);
+ memcpy(&command_line, TAGVALPTR(atag), atag->size);
memcpy(saved_command_line, command_line, CL_SIZE);
saved_command_line[CL_SIZE-1] = '\0';
@@ -280,8 +233,8 @@ void setup_arch(char **cmdline_p,
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE) {
- initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
- initrd_end = initrd_start+INITRD_SIZE;
+ 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",
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index b744823b1..fdbc86558 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -4,6 +4,7 @@
* 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/kernel.h>
@@ -15,20 +16,8 @@
#include <asm/asm.h>
#include <asm/bitops.h>
+#include <asm/pgtable.h>
#include <asm/uaccess.h>
-#include <asm/cache.h>
-#include <asm/mipsconfig.h>
-#include <asm/sgidefs.h>
-
-/*
- * Linux/MIPS misstreats the SA_NOMASK flag for signal handlers.
- * Actually this is a bug in libc that was made visible by the POSIX.1
- * changes in Linux/MIPS 2.0.1. To keep old binaries alive enable
- * this define but note that this is just a hack with sideeffects, not a
- * perfect compatibility mode. This will go away, so rebuild your
- * executables with libc 960709 or newer.
- */
-#define CONF_NOMASK_BUG_COMPAT
#define _S(nr) (1<<((nr)-1))
@@ -36,21 +25,19 @@
asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
-
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
{
k_sigset_t new_set, old_set = current->blocked;
+ int error;
if (set) {
- if (!access_ok(VERIFY_READ, set, sizeof(sigset_t)))
- return -EFAULT;
-
- __get_user(new_set, to_k_sigset_t(set));
- new_set &= _BLOCKABLE;
-
+ error = verify_area(VERIFY_READ, set, sizeof(sigset_t));
+ if (error)
+ return error;
+ new_set = *to_k_sigset_t(set) & _BLOCKABLE;
switch (how) {
case SIG_BLOCK:
current->blocked |= new_set;
@@ -73,14 +60,14 @@ asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
}
}
if (oset) {
- if(!access_ok(VERIFY_WRITE, oset, sizeof(sigset_t)))
- return -EFAULT;
- __put_user(old_set, &oset->__sigbits[0]);
- __put_user(0, &oset->__sigbits[1]);
- __put_user(0, &oset->__sigbits[2]);
- __put_user(0, &oset->__sigbits[3]);
+ error = verify_area(VERIFY_WRITE, oset, sizeof(sigset_t));
+ if (error)
+ return error;
+ put_user(old_set, &oset->__sigbits[0]);
+ put_user(0, &oset->__sigbits[1]);
+ put_user(0, &oset->__sigbits[2]);
+ put_user(0, &oset->__sigbits[3]);
}
-
return 0;
}
@@ -95,17 +82,15 @@ asmlinkage int sys_sigsuspend(struct pt_regs *regs)
mask = current->blocked;
uset = (sigset_t *)(long) regs->regs[4];
- if (!access_ok(VERIFY_READ, uset, sizeof(sigset_t)))
+ if (verify_area(VERIFY_READ, uset, sizeof(sigset_t)))
return -EFAULT;
-
- __get_user(kset, to_k_sigset_t(uset));
-
+ kset = *to_k_sigset_t(uset);
current->blocked = kset & _BLOCKABLE;
regs->regs[2] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(mask, regs))
+ if (do_signal(mask,regs))
return -EINTR;
}
@@ -129,11 +114,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
current->blocked = context->sc_sigset.__sigbits[0] & _BLOCKABLE;
regs->cp0_epc = context->sc_pc;
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- for(i = 31;i >= 0;i--)
- __get_user(regs->regs[i], &context->sc_regs[i]);
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+
/*
* We only allow user processes in 64bit mode (n32, 64 bit ABI) to
* restore the upper half of registers.
@@ -146,7 +127,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
__get_user(regs->regs[i], &context->sc_regs[i]);
regs->regs[i] = (int) regs->regs[i];
}
-#endif
+
__get_user(regs->hi, &context->sc_mdhi);
__get_user(regs->lo, &context->sc_mdlo);
restore_fp_context(context);
@@ -159,7 +140,8 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
/*
* Don't let your children do this ...
*/
- asm( "move\t$29,%0\n\t"
+ asm __volatile__(
+ "move\t$29,%0\n\t"
"j\tret_from_sys_call"
:/* no outputs */
:"r" (regs));
@@ -184,7 +166,7 @@ badframe:
* when the signal handler is returned.
*
* The signal handler will be called with ra pointing to code1 (see below) and
- * signal number and pointer to the saved sigcontext as the two parameters.
+ * one parameters in a0 (signum).
*
* usp -> [unused] ; first free word on stack
* arg save space ; 16/32 bytes arg. save space
@@ -217,17 +199,11 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
frame = (struct sc *) (long) regs->regs[29];
frame--;
- /*
- * We realign the stack to an adequate boundary for the architecture.
- * The assignment to sc had to be moved over the if to prevent
- * GCC from throwing warnings.
- */
- frame = (struct sc *)((unsigned long)frame & ALMASK);
- sc = &frame->scc;
- if (!access_ok(VERIFY_WRITE, frame, sizeof (struct sc))) {
+ /* We realign the stack to an adequate boundary for the architecture. */
+ if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)))
do_exit(SIGSEGV);
- return;
- }
+ frame = (struct sc *)((unsigned long)frame & ALMASK);
+ sc = &frame->scc;
/*
* Set up the return code ...
@@ -238,82 +214,75 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
* syscall
* .set reorder
*/
- __put_user(0x27bd0000 + scc_offset, &frame->code[0]);
+ __put_user(0x27bd0000 + scc_offset, &frame->code[0]);
__put_user(0x24020000 + __NR_sigreturn, &frame->code[1]);
- __put_user(0x0000000c, &frame->code[2]);
+ __put_user(0x0000000c, &frame->code[2]);
/*
* Flush caches so that the instructions will be correctly executed.
*/
- cacheflush((unsigned long)frame->code, sizeof (frame->code),
- CF_BCACHE|CF_ALL);
+ flush_cache_sigtramp((unsigned long) frame->code);
/*
* Set up the "normal" sigcontext
*/
- sc->sc_pc = regs->cp0_epc; /* Program counter */
- sc->sc_status = regs->cp0_status; /* Status register */
+ __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_CU0) != 0, &sc->sc_ownedfp);
+ __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp);
__put_user(oldmask, &sc->sc_sigset.__sigbits[0]);
__put_user(0, &sc->sc_sigset.__sigbits[1]);
__put_user(0, &sc->sc_sigset.__sigbits[2]);
__put_user(0, &sc->sc_sigset.__sigbits[3]);
- regs->regs[4] = signr; /* Args for handler */
- regs->regs[5] = (long) frame; /* Ptr to sigcontext */
+ 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 = regs->regs[25] /* "return" to the first handler */
- = (unsigned long) sa->sa_handler;
+ regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */
+ regs->regs[25] = regs->cp0_epc; /* PIC shit... */
}
-/*
- * OK, we're invoking a handler
- */
-static inline void
-handle_signal(unsigned long signr, struct sigaction *sa,
- unsigned long oldmask, struct pt_regs * regs)
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs * regs)
{
- /* are we from a failed system call? */
- if (regs->orig_reg2 >= 0 && regs->regs[7]) {
- /* If so, check system call restarting.. */
- switch (regs->regs[2]) {
- case ERESTARTNOHAND:
- regs->regs[2] = EINTR;
- break;
-
- case ERESTARTSYS:
- if (!(sa->sa_flags & SA_RESTART)) {
- regs->regs[2] = EINTR;
- break;
- }
- /* fallthrough */
- case ERESTARTNOINTR:
- regs->regs[7] = regs->orig_reg7;
- regs->cp0_epc -= 8;
- }
- }
-
- /* set up the stack frame */
setup_frame(sa, regs, signr, oldmask);
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
-#ifdef CONF_NOMASK_BUG_COMPAT
- current->blocked |= *to_k_sigset_t(&sa->sa_mask);
-#else
if (!(sa->sa_flags & SA_NOMASK))
- current->blocked |= (*to_k_sigset_t(&sa->sa_mask) |
- _S(signr)) & _BLOCKABLE;
-#endif
+ current->blocked |=
+ ((*to_k_sigset_t(&sa->sa_mask) | _S(signr)) & _BLOCKABLE);
+}
+
+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
@@ -326,9 +295,14 @@ handle_signal(unsigned long signr, struct sigaction *sa,
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
{
unsigned long mask = ~current->blocked;
- unsigned long signr;
+ unsigned long signr, r0 = regs->regs[0];
+ unsigned long r7 = regs->orig_reg7;
struct sigaction * sa;
+#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);
@@ -365,10 +339,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
- case SIGTSTP: case SIGTTIN: case SIGTTOU:
- if (is_orphaned_pgrp(current->pgrp))
- continue;
- case SIGSTOP:
+ case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (current->flags & PF_PTRACED)
continue;
current->state = TASK_STOPPED;
@@ -380,8 +351,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
- case SIGABRT: case SIGFPE: case SIGSEGV:
- case SIGBUS:
+ case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
@@ -393,19 +363,39 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
do_exit(signr);
}
}
+ /*
+ * OK, we're invoking a handler
+ */
+#if 0
+ printk("[%s:%d] send sig1: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
+ current->comm, current->pid, r0, r7, regs->regs[2]);
+#endif
+ if(r0)
+ syscall_restart(r0, regs->orig_reg2,
+ r7, regs, sa);
+#if 0
+ printk("send sig2: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
+ r0, r7, regs->regs[2]);
+#endif
handle_signal(signr, sa, oldmask, regs);
return 1;
}
-
- /* Did we come from a system call? */
- if (regs->orig_reg2 >= 0) {
- /* Restart the system call - no handlers present */
- if (regs->regs[2] == -ERESTARTNOHAND ||
- regs->regs[2] == -ERESTARTSYS ||
- regs->regs[2] == -ERESTARTNOINTR) {
- regs->regs[2] = regs->orig_reg2;
- regs->cp0_epc -= 8;
- }
+ /*
+ * 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 0
+ printk("[%s:%d] send sig3: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
+ current->comm, current->pid, r0, r7, regs->regs[2]);
+#endif
+ 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;
}
return 0;
}
@@ -417,5 +407,5 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
*/
asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
{
- return -ENOSYS;
+ return -ENOSYS;
}
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 144a3c905..3b595e05d 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -12,7 +12,9 @@
* table.
*/
#undef CONF_PRINT_SYSCALLS
+#undef CONF_DEBUG_IRIX
+#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/mman.h>
@@ -20,25 +22,16 @@
#include <linux/unistd.h>
#include <asm/branch.h>
#include <asm/ptrace.h>
-#include <asm/uaccess.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[];
-/*
- * The pipe syscall has a unusual calling convention. We return the two
- * filedescriptors in the result registers v0/v1. The syscall wrapper
- * from libc places these results in the array to which the argument of
- * pipe points to. This is like other MIPS operating systems and unlike
- * Linux/i386 where the kernel itself places the results in the file
- * descriptor array itself. This calling convention also has the advantage
- * of lower overhead because we don't need to call verify_area.
- */
asmlinkage int sys_pipe(struct pt_regs *regs)
{
int fd[2];
@@ -74,9 +67,10 @@ asmlinkage int sys_idle(void)
current->counter = -100;
for (;;) {
/*
- * Not all MIPS R-series CPUs have the wait instruction.
+ * R4[236]00 have wait, R4[04]00 don't.
* FIXME: We should save power by reducing the clock where
- * possible.
+ * possible. Should help alot for battery powered
+ * R4200/4300i systems.
*/
if (wait_available && !need_resched)
__asm__(".set\tmips3\n\t"
@@ -86,33 +80,6 @@ asmlinkage int sys_idle(void)
}
}
-#if 0
-/*
- * RISC/os compatible SysV flavoured fork(2) syscall.
- *
- * This call has a different calling sequence:
- * child return value: pid of parent, secondary result = 1.
- * parent return value: pid of child, secondary result value = 0.
- * error: errno, secondary result = 0.
- */
-asmlinkage int sys_sysv_fork(struct pt_regs *regs)
-{
- int pid;
-
- pid = do_fork(SIGCHLD, regs->regs[29], regs);
- if (pid == 0) { /* child */
- regs->regs[3] = 1;
- return current->p_pptr->pid;
- } /* parent or error */
-
- regs->regs[3] = 0;
- return pid;
-}
-#endif
-
-/*
- * Normal Linux fork(2) syscall
- */
asmlinkage int sys_fork(struct pt_regs *regs)
{
return do_fork(SIGCHLD, regs->regs[29], regs);
@@ -144,33 +111,73 @@ asmlinkage int sys_execve(struct pt_regs *regs)
error = do_execve(filename, (char **) (long)regs->regs[5],
(char **) (long)regs->regs[6], regs);
putname(filename);
-
return error;
}
/*
* Do the indirect syscall syscall.
*/
-asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- unsigned long a6)
+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);
}
@@ -190,13 +197,20 @@ static char *sfnames[] = {
};
#endif
-asmlinkage void do_sys(struct pt_regs *regs)
+#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
+#define SYS(fun, narg) #fun,
+static char *irix_sys_names[] = {
+#include "irix5sys.h"
+};
+#endif
+
+void do_sys(struct pt_regs *regs)
{
unsigned long syscallnr, usp;
syscall_t syscall;
int errno, narg;
- /* Skip syscall instruction */
+ /* Skip syscall instruction */
if (delay_slot(regs)) {
/*
* By convention "li v0,<syscallno>" is always preceeding
@@ -211,70 +225,121 @@ asmlinkage void do_sys(struct pt_regs *regs)
syscallnr = regs->regs[2];
if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
goto illegal_syscall;
+
syscall = sys_call_table[syscallnr];
+ if (syscall == NULL)
+ goto illegal_syscall;
+ narg = sys_narg_table[syscallnr];
#ifdef CONF_PRINT_SYSCALLS
- printk("do_sys(): %s()", sfnames[syscallnr - __NR_Linux]);
+ 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
- narg = sys_narg_table[syscallnr];
if (narg > 4) {
/*
* Verify that we can safely get the additional parameters
- * from the user stack.
+ * from the user stack. Of course I could read the params
+ * from unaligned addresses ... Consider this a programming
+ * course caliber .45.
*/
usp = regs->regs[29];
if (usp & 3) {
printk("unaligned usp\n");
- do_exit(SIGBUS);
+ 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))) {
- errno = -EFAULT;
- goto syscall_error;
+ (narg - 4) * sizeof(unsigned long))) {
+ regs->regs[2] = EFAULT;
+ regs->regs[7] = 1;
+ return;
}
}
- if ((current->flags & PF_TRACESYS) == 0) {
+ if ((current->flags & PF_TRACESYS) == 0)
+ {
errno = do_syscalls(regs, syscall, narg);
- if (errno < 0)
- goto syscall_error;
-
+ if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) {
+ goto bad_syscall;
+ }
regs->regs[2] = errno;
regs->regs[7] = 0;
- } else {
+ }
+ else
+ {
syscall_trace();
errno = do_syscalls(regs, syscall, narg);
- if (errno < 0) {
+ if (errno < 0 || current->errno)
+ {
regs->regs[2] = -errno;
regs->regs[7] = 1;
- } else {
+ }
+ else
+ {
regs->regs[2] = errno;
regs->regs[7] = 0;
}
syscall_trace();
}
-#ifdef CONF_PRINT_SYSCALLS
+#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;
-syscall_error:
- regs->regs[2] = -errno;
+bad_syscall:
+ regs->regs[0] = regs->regs[2] = -errno;
regs->regs[7] = 1;
-#ifdef CONF_PRINT_SYSCALLS
- printk(" returning: syscall_error, errno=%d\n", -errno);
+#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->regs[2] = ENOSYS;
regs->regs[7] = 1;
-#ifdef CONF_PRINT_SYSCALLS
- printk(" returning: illegal_syscall\n");
+#if defined(CONF_PRINT_SYSCALLS) || \
+ (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
+ if(syscallnr >= 1000 && syscallnr < 2000)
+ printk(" returning: illegal_syscall\n");
#endif
return;
}
diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
index 6a398c92d..723cb5e34 100644
--- a/arch/mips/kernel/syscalls.h
+++ b/arch/mips/kernel/syscalls.h
@@ -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)
@@ -201,5 +201,3 @@ 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)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
new file mode 100644
index 000000000..c54f83595
--- /dev/null
+++ b/arch/mips/kernel/sysirix.c
@@ -0,0 +1,2100 @@
+/* $Id: sysirix.c,v 1.14 1996/07/14 01:59:51 dm 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/utsname.h>
+
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+/* 2,000 lines of complete and utter shit coming up... */
+
+/* Utility routines. */
+static inline struct task_struct *find_process_by_pid(pid_t pid)
+{
+ struct task_struct *p, *q;
+
+ if (pid == 0)
+ p = current;
+ else {
+ p = 0;
+ for_each_task(q) {
+ if (q && q->pid == pid) {
+ p = q;
+ break;
+ }
+ }
+ }
+ return p;
+}
+
+/* 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;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ cmd = regs->regs[base + 4];
+ switch(cmd) {
+ case MP_PGSIZE:
+ return PAGE_SIZE;
+ break;
+
+ default:
+ printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
+ current->comm, current->pid, (int)cmd);
+ error = -EINVAL;
+ break;
+ }
+
+ 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;
+
+ 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);
+ return NR_TASKS;
+
+ case PR_ISBLOCKED: {
+ struct task_struct *task;
+
+ printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
+ current->comm, current->pid);
+ task = find_process_by_pid(regs->regs[base + 5]);
+ if(!task)
+ return -ESRCH;
+ return (task->next_run ? 0 : 1);
+ /* Can _your_ OS find this out that fast? */
+ }
+
+ 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;
+ return value;
+ }
+ if(value > current->rlim[RLIMIT_STACK].rlim_max)
+ return -EINVAL;
+ current->rlim[RLIMIT_STACK].rlim_cur = value;
+ return value;
+ }
+
+ case PR_GETSTACKSIZE:
+ printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
+ current->comm, current->pid);
+ return current->rlim[RLIMIT_STACK].rlim_cur;
+
+ case PR_MAXPPROCS:
+ printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+ current->comm, current->pid);
+ return 1;
+
+ case PR_UNBLKONEXEC:
+ printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ 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().
+ */
+ return -EINVAL;
+
+ case PR_RESIDENT:
+ printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
+ current->comm, current->pid);
+ return 0; /* Compatability indeed. */
+
+ case PR_ATTACHADDR:
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case PR_DETACHADDR:
+ printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case PR_TERMCHILD:
+ printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case PR_GETSHMASK:
+ printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
+ current->comm, current->pid);
+ return -EINVAL; /* Until I have the sproc() stuff in. */
+
+ case PR_GETNSHARE:
+ return 0; /* Until I have the sproc() stuff in. */
+
+ case PR_COREPID:
+ printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case PR_ATTACHADDRPERM:
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ 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;
+ }
+
+ 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;
+
+ 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.... */
+ return clear_user(buf, 64);
+ }
+
+ 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)
+ return retval;
+ for_each_task(p) {
+ if(p->pid == pid)
+ goto found0;
+ }
+ return -ESRCH;
+
+ found0:
+ copy_to_user(buf, p->comm, 16);
+ return 0;
+ }
+
+ case SGI_SETPGID: {
+ int error;
+
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] setpgid(%d, %d) ",
+ current->comm, current->pid,
+ (int) regs->regs[base + 5], (int)regs->regs[base + 6]);
+#endif
+ error = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);
+
+#ifdef DEBUG_PROCGRPS
+ printk("error=%d\n", error);
+#endif
+ return error;
+ }
+
+ case SGI_SYSCONF: {
+ switch(regs->regs[base + 5]) {
+ case 1:
+ return (MAX_ARG_PAGES >> 4); /* XXX estimate... */
+ case 2:
+ return NR_TASKS;
+ case 3:
+ return HZ;
+ case 4:
+ return NGROUPS;
+ case 5:
+ return NR_OPEN;
+ case 6:
+ return 1;
+ case 7:
+ return 1;
+ case 8:
+ return 199009;
+ case 11:
+ return PAGE_SIZE;
+ case 12:
+ return 4;
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ return 0;
+ case 31:
+ return 32;
+ default:
+ return -EINVAL;
+ };
+ }
+
+ case SGI_SETGROUPS:
+ return sys_setgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+
+ case SGI_GETGROUPS:
+ return sys_getgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+
+ case SGI_RUSAGE: {
+ struct rusage *ru = (struct rusage *) regs->regs[base + 6];
+
+ switch((int) regs->regs[base + 5]) {
+ case 0:
+ /* rusage self */
+ return getrusage(current, RUSAGE_SELF, ru);
+
+ case -1:
+ /* rusage children */
+ return getrusage(current, RUSAGE_CHILDREN, ru);
+
+ default:
+ return -EINVAL;
+ };
+ }
+
+ case SGI_SSYNC:
+ sys_sync();
+ return 0;
+
+ case SGI_GETSID: {
+ int error;
+
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
+ (int) regs->regs[base + 5]);
+#endif
+ error = sys_getsid(regs->regs[base + 5]);
+#ifdef DEBUG_PROCGRPS
+ printk("error=%d\n", error);
+#endif
+ return error;
+ }
+
+ case SGI_ELFMAP:
+ retval = irix_mapelf((int) regs->regs[base + 5],
+ (struct elf_phdr *) regs->regs[base + 6],
+ (int) regs->regs[base + 7]);
+ return retval;
+
+ case SGI_TOSSTSAVE:
+ /* XXX We don't need to do anything? */
+ return 0;
+
+ case SGI_FP_BCOPY:
+ return 0;
+
+ 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;
+ }
+ }
+ return -EINVAL;
+ }
+
+ default:
+ printk("irix_syssgi: Unsupported command %d\n", (int)cmd);
+ return -EINVAL;
+ };
+}
+
+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;
+
+ if (brk < current->mm->end_code)
+ return -ENOMEM;
+
+ newbrk = PAGE_ALIGN(brk);
+ oldbrk = PAGE_ALIGN(mm->brk);
+ if (oldbrk == newbrk) {
+ mm->brk = brk;
+ return 0;
+ }
+
+ /*
+ * Always allow shrinking brk
+ */
+ if (brk <= current->mm->brk) {
+ mm->brk = brk;
+ do_munmap(newbrk, oldbrk-newbrk);
+ return 0;
+ }
+ /*
+ * Check against rlimit and stack..
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (brk - mm->end_code > rlim)
+ return -ENOMEM;
+
+ /*
+ * Check against existing mmap mappings.
+ */
+ if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
+ return -ENOMEM;
+
+ /*
+ * Check if we have enough memory..
+ */
+ if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
+ return -ENOMEM;
+
+ /*
+ * 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);
+
+ return 0;
+}
+
+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)
+{
+ if(!suser())
+ return -EPERM;
+ cli();
+ xtime.tv_sec = value;
+ xtime.tv_usec = 0;
+ time_state = TIME_ERROR;
+ time_maxerror = MAXPHASE;
+ time_esterror = MAXPHASE;
+ sti();
+ return 0;
+}
+
+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;
+
+ 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++;
+ return oldalarm;
+}
+
+asmlinkage int irix_pause(void)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ 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)
+{
+ printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+ current->comm, current->pid,
+ dev_name, dir_name, flags, type, data, datalen);
+ return sys_mount(dev_name, dir_name, type, flags, data);
+ /* return -EINVAL; */
+}
+
+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)
+ return -EINVAL;
+ error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
+ if (error)
+ return error;
+ error = namei(path,&inode);
+ if (error)
+ return error;
+ if (!inode->i_sb->s_op->statfs) {
+ iput(inode);
+ return -ENOSYS;
+ }
+
+ 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]);
+ }
+
+ return 0;
+}
+
+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;
+
+ error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
+ if (error)
+ return error;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs)
+ return -ENOSYS;
+
+ 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]);
+ }
+
+ return 0;
+}
+
+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;
+
+#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
+ return error;
+}
+
+asmlinkage int irix_times(struct tms * tbuf)
+{
+ if (tbuf) {
+ int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+ if (error)
+ return error;
+ __put_user(current->utime,&tbuf->tms_utime);
+ __put_user(current->stime,&tbuf->tms_stime);
+ __put_user(current->cutime,&tbuf->tms_cutime);
+ __put_user(current->cstime,&tbuf->tms_cstime);
+ }
+
+ return 0;
+}
+
+asmlinkage int irix_exec(struct pt_regs *regs)
+{
+ int error, base = 0;
+ char * filename;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ error = getname((char *) (long)regs->regs[base + 4], &filename);
+ if (error)
+ return error;
+ error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+ (char **) 0, regs);
+ putname(filename);
+ return error;
+}
+
+asmlinkage int irix_exece(struct pt_regs *regs)
+{
+ int error, base = 0;
+ char * filename;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ error = getname((char *) (long)regs->regs[base + 4], &filename);
+ if (error)
+ return error;
+ error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+ (char **) (long)regs->regs[base + 6], regs);
+ putname(filename);
+ return error;
+}
+
+/* sys_poll() support... */
+#define POLL_ROUND_UP(x,y) (((x)+(y)-1)/(y))
+
+#define POLLIN 1
+#define POLLPRI 2
+#define POLLOUT 4
+#define POLLERR 8
+#define POLLHUP 16
+#define POLLNVAL 32
+#define POLLRDNORM 64
+#define POLLWRNORM POLLOUT
+#define POLLRDBAND 128
+#define POLLWRBAND 256
+
+#define LINUX_POLLIN (POLLRDNORM | POLLRDBAND | POLLIN)
+#define LINUX_POLLOUT (POLLWRBAND | POLLWRNORM | POLLOUT)
+#define LINUX_POLLERR (POLLERR)
+
+static inline void free_wait(select_table * p)
+{
+ struct select_table_entry * entry = p->entry + p->nr;
+
+ while (p->nr > 0) {
+ p->nr--;
+ entry--;
+ remove_wait_queue(entry->wait_address,&entry->wait);
+ }
+}
+
+
+/* Copied directly from fs/select.c */
+static int check(int flag, select_table * wait, struct file * file)
+{
+ struct inode * inode;
+ struct file_operations *fops;
+ int (*select) (struct inode *, struct file *, int, select_table *);
+
+ inode = file->f_inode;
+ if ((fops = file->f_op) && (select = fops->select))
+ return select(inode, file, flag, wait)
+ || (wait && select(inode, file, flag, NULL));
+ if (S_ISREG(inode->i_mode))
+ return 1;
+ return 0;
+}
+
+struct poll {
+ int fd;
+ short events;
+ short revents;
+};
+
+int irix_poll(struct poll * ufds, size_t nfds, int timeout)
+{
+ int i,j, count, fdcount, error, retflag;
+ struct poll * fdpnt;
+ struct poll * fds, *fds1;
+ select_table wait_table, *wait;
+ struct select_table_entry *entry;
+
+ if ((error = verify_area(VERIFY_READ, ufds, nfds*sizeof(struct poll))))
+ return error;
+
+ if (nfds > NR_OPEN)
+ return -EINVAL;
+
+ if (!(entry = (struct select_table_entry*)__get_free_page(GFP_KERNEL))
+ || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL)))
+ return -ENOMEM;
+
+ copy_from_user(fds, ufds, nfds*sizeof(struct poll));
+
+ if (timeout < 0)
+ current->timeout = 0x7fffffff;
+ else {
+ current->timeout = jiffies + POLL_ROUND_UP(timeout, (1000/HZ));
+ if (current->timeout <= jiffies)
+ current->timeout = 0;
+ }
+
+ count = 0;
+ wait_table.nr = 0;
+ wait_table.entry = entry;
+ wait = &wait_table;
+
+ for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
+ i = fdpnt->fd;
+ fdpnt->revents = 0;
+ if (!current->files->fd[i] || !current->files->fd[i]->f_inode)
+ fdpnt->revents = POLLNVAL;
+ }
+repeat:
+ current->state = TASK_INTERRUPTIBLE;
+ for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
+ i = fdpnt->fd;
+
+ if(i < 0) continue;
+ if (!current->files->fd[i] || !current->files->fd[i]->f_inode) continue;
+
+ if ((fdpnt->events & LINUX_POLLIN)
+ && check(SEL_IN, wait, current->files->fd[i])) {
+ retflag = 0;
+ if (fdpnt->events & POLLIN)
+ retflag = POLLIN;
+ if (fdpnt->events & POLLRDNORM)
+ retflag = POLLRDNORM;
+ fdpnt->revents |= retflag;
+ count++;
+ wait = NULL;
+ }
+
+ if ((fdpnt->events & LINUX_POLLOUT) &&
+ check(SEL_OUT, wait, current->files->fd[i])) {
+ fdpnt->revents |= (LINUX_POLLOUT & fdpnt->events);
+ count++;
+ wait = NULL;
+ }
+
+ if (check(SEL_EX, wait, current->files->fd[i])) {
+ fdpnt->revents |= POLLHUP;
+ count++;
+ wait = NULL;
+ }
+ }
+
+ if ((current->signal & (~current->blocked)))
+ return -EINTR;
+
+ wait = NULL;
+ if (!count && current->timeout > jiffies) {
+ schedule();
+ goto repeat;
+ }
+
+ free_wait(&wait_table);
+ free_page((unsigned long) entry);
+
+ /* OK, now copy the revents fields back to user space. */
+ fds1 = fds;
+ fdcount = 0;
+ for(i=0; i < (int)nfds; i++, ufds++, fds++) {
+ if (fds->revents) {
+ fdcount++;
+ }
+ put_user(fds->revents, &ufds->revents);
+ }
+ kfree(fds1);
+ current->timeout = 0;
+ current->state = TASK_RUNNING;
+ return fdcount;
+}
+
+asmlinkage unsigned long irix_gethostid(void)
+{
+ printk("[%s:%d]: irix_gethostid() called...\n",
+ current->comm, current->pid);
+ return -EINVAL;
+}
+
+asmlinkage unsigned long irix_sethostid(unsigned long val)
+{
+ printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
+ current->comm, current->pid, val);
+ 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;
+
+ if(len > (__NEW_UTS_LEN - 1))
+ len = __NEW_UTS_LEN - 1;
+ error = verify_area(VERIFY_WRITE, name, len);
+ if(error)
+ return -EFAULT;
+ if(copy_to_user(name, system_utsname.domainname, len))
+ return -EFAULT;
+
+ return 0;
+}
+
+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;
+
+ old_fs = get_fs(); set_fs(get_ds());
+ error = sys_llseek(fd, offhi, offlow, &junk, base);
+ set_fs(old_fs);
+
+ if(error)
+ return error;
+ return (int) junk;
+}
+
+asmlinkage int irix_sginap(int ticks)
+{
+ if(ticks) {
+ current->timeout = ticks + jiffies;
+ current->state = TASK_INTERRUPTIBLE;
+ }
+ schedule();
+ return 0;
+}
+
+asmlinkage int irix_sgikopt(char *istring, char *ostring, int len)
+{
+ return -EINVAL;
+}
+
+asmlinkage int irix_gettimeofday(struct timeval *tv)
+{
+ return copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0;
+}
+
+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;
+
+ if(!(flags & MAP_ANONYMOUS)) {
+ if(fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ retval = do_mmap(file, addr, len, prot, flags, offset);
+ return retval;
+}
+
+asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
+{
+ printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+ current->comm, current->pid, addr, len, behavior);
+ return -EINVAL;
+}
+
+asmlinkage int irix_pagelock(char *addr, int len, int op)
+{
+ printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
+ current->comm, current->pid, addr, len, op);
+ return -EINVAL;
+}
+
+asmlinkage int irix_quotactl(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_quotactl()\n",
+ current->comm, current->pid);
+ return -EINVAL;
+}
+
+asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
+{
+ int error;
+
+#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
+ return error;
+}
+
+asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
+{
+ printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+ current->comm, current->pid, cmd, buf, cnt);
+ 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)
+{
+ if(copy_to_user(system_utsname.sysname, buf->sysname, 65))
+ return -EFAULT;
+ if(copy_to_user(system_utsname.nodename, buf->nodename, 65))
+ return -EFAULT;
+ if(copy_to_user(system_utsname.release, buf->release, 65))
+ return -EFAULT;
+ if(copy_to_user(system_utsname.version, buf->version, 65))
+ return -EFAULT;
+ if(copy_to_user(system_utsname.machine, buf->machine, 65))
+ return -EFAULT;
+
+ return 1;
+}
+
+#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)
+{
+#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 errno, old_fs;
+
+ old_fs = get_fs(); set_fs(get_ds());
+ errno = sys_newstat(filename, &kb);
+ set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+ errno = irix_xstat32_xlate(&kb, statbuf);
+ return errno;
+ }
+
+ case 3: {
+ int errno = sys_newstat(filename, statbuf);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+
+ irix_xstat64_xlate(statbuf);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
+{
+#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 errno, old_fs;
+
+ old_fs = get_fs(); set_fs(get_ds());
+ errno = sys_newlstat(filename, &kb);
+ set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+ errno = irix_xstat32_xlate(&kb, statbuf);
+ return errno;
+ }
+
+ case 3: {
+ int errno = sys_newlstat(filename, statbuf);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+
+ irix_xstat64_xlate(statbuf);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
+{
+#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 errno, old_fs;
+
+ old_fs = get_fs(); set_fs(get_ds());
+ errno = sys_newfstat(fd, &kb);
+ set_fs(old_fs);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+ errno = irix_xstat32_xlate(&kb, statbuf);
+ return errno;
+ }
+
+ case 3: {
+ int errno = sys_newfstat(fd, statbuf);
+#ifdef DEBUG_XSTAT
+ printk("errno[%d]\n", errno);
+#endif
+ if(errno)
+ return errno;
+
+ irix_xstat64_xlate(statbuf);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+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)
+{
+ printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+ current->comm, current->pid, ver, filename, mode, (int) dev);
+ switch(ver) {
+ case 2:
+ return sys_mknod(filename, mode, dev);
+
+ default:
+ return -EINVAL;
+ };
+}
+
+asmlinkage int irix_swapctl(int cmd, char *arg)
+{
+ printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
+ current->comm, current->pid, cmd, arg);
+ 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;
+
+ 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)
+ return error;
+ error = namei(fname, &inode);
+ if(error)
+ return error;
+ if(!inode->i_sb->s_op->statfs) {
+ iput(inode);
+ return -ENOSYS;
+ }
+
+ 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]);
+
+ return 0;
+}
+
+asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
+{
+ struct inode * inode;
+ struct statfs kbuf;
+ struct file *file;
+ int error, old_fs, i;
+
+ 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)
+ return error;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs)
+ return -ENOSYS;
+
+ 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]);
+
+ return 0;
+}
+
+#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)
+{
+ /* Do follow any and all links... */
+ return chown_common(fname, uid, gid, FOLLOW_LINKS);
+}
+
+asmlinkage int irix_lchown(char *fname, int uid, int gid)
+{
+ /* Do _not_ follow any links... */
+ return chown_common(fname, uid, gid, NOFOLLOW_LINKS);
+}
+
+asmlinkage int irix_priocntl(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_priocntl()\n",
+ current->comm, current->pid);
+ return -EINVAL;
+}
+
+asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
+{
+ printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+ current->comm, current->pid, pid, sig, code, val);
+ 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)
+{
+ if(size1)
+ return -EINVAL;
+ return sys_truncate(name, size2);
+}
+
+asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2)
+{
+ if(size1)
+ return -EINVAL;
+ return sys_ftruncate(fd, size2);
+}
+
+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;
+
+ 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)
+ return error;
+ 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)
+ return error;
+ __get_user(flags, &sp[0]);
+ __get_user(fd, &sp[1]);
+ __get_user(off1, &sp[2]);
+ __get_user(off2, &sp[3]);
+ }
+ if(off1)
+ return -EINVAL;
+ return sys_mmap(addr, (size_t) len, prot, flags, fd, off2);
+}
+
+asmlinkage int irix_dmi(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_dmi()\n",
+ current->comm, current->pid);
+ return -EINVAL;
+}
+
+asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
+ int off1, int off2)
+{
+ printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+ current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+ return -EINVAL;
+}
+
+asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
+ int off1, int off2)
+{
+ printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+ current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+ 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)
+{
+ 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);
+ 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)
+ return error;
+ error = namei(fname, &inode);
+ if(error)
+ return error;
+ if(!inode->i_sb->s_op->statfs) {
+ iput(inode);
+ return -ENOSYS;
+ }
+
+ 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]);
+
+ return 0;
+}
+
+asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
+{
+ struct inode * inode;
+ struct statfs kbuf;
+ struct file *file;
+ int error, old_fs, i;
+
+ 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)
+ return error;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs)
+ return -ENOSYS;
+
+ 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]);
+
+ return 0;
+}
+
+asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
+{
+ int errno;
+
+ printk("[%s:%d] irix_getmountid(%s, %p)\n",
+ current->comm, current->pid, fname, midbuf);
+ errno = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
+ if(errno)
+ return errno;
+
+ /*
+ * 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]);
+
+ return 0;
+}
+
+asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
+ unsigned long arg, unsigned long sp, int slen)
+{
+ printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+ current->comm, current->pid, entry, mask, arg, sp, slen);
+ 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);
+
+#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)
+ return -EINVAL;
+ 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;
+
+ return 0;
+}
+
+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;
+
+#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]))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->readdir)
+ return -ENOTDIR;
+ if(verify_area(VERIFY_WRITE, dirent, count) ||
+ verify_area(VERIFY_WRITE, eob, sizeof(*eob)))
+ return -EFAULT;
+ __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)
+ return error;
+ lastdirent = buf.previous;
+ if (!lastdirent)
+ return buf.error;
+ lastdirent->d_off = (u32) file->f_pos;
+#ifdef DEBUG_GETDENTS
+ printk("eob=%d returning %d\n", *eob, count - buf.count);
+#endif
+ return count - buf.count;
+}
+
+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);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ 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;
+
+ return 0;
+}
+
+asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
+{
+ struct file *file;
+ struct irix_dirent64 *lastdirent;
+ struct irix_dirent64_callback buf;
+ int error;
+
+#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]))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->readdir)
+ return -ENOTDIR;
+ if(verify_area(VERIFY_WRITE, dirent, cnt))
+ return -EFAULT;
+ if(cnt < (sizeof(struct irix_dirent64) + 255))
+ return -EINVAL;
+
+ 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)
+ return error;
+ lastdirent = buf.previous;
+ if (!lastdirent)
+ return buf.error;
+ lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+ printk("returning %d\n", cnt - buf.count);
+#endif
+ return cnt - buf.count;
+}
+
+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;
+
+#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]))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->readdir)
+ return -ENOTDIR;
+ if(verify_area(VERIFY_WRITE, dirent, cnt) ||
+ verify_area(VERIFY_WRITE, eob, sizeof(*eob)))
+ return -EFAULT;
+ if(cnt < (sizeof(struct irix_dirent64) + 255))
+ return -EINVAL;
+
+ *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)
+ return error;
+ lastdirent = buf.previous;
+ if (!lastdirent)
+ return buf.error;
+ lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+ printk("eob=%d returning %d\n", *eob, cnt - buf.count);
+#endif
+ return cnt - buf.count;
+}
+
+asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long arg)
+{
+ switch(op) {
+ case 1:
+ /* Reboot */
+ printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 2:
+ /* Shutdown */
+ printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 4:
+ /* Remount-root */
+ printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 8:
+ /* Kill all tasks. */
+ printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 256:
+ /* Set magic mushrooms... */
+ printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+ current->comm, current->pid, (int) func);
+ return -EINVAL;
+
+ default:
+ printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
+ current->comm, current->pid, (int) op);
+ return -EINVAL;
+ };
+}
+
+asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
+{
+ switch(type) {
+ case 0:
+ /* uname() */
+ return irix_uname((struct iuname *)inbuf);
+
+ case 2:
+ /* ustat() */
+ printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 3:
+ /* fusers() */
+ printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ default:
+ printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
+ current->comm, current->pid, (int) type);
+ return -EINVAL;
+ }
+}
+
+#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;
+
+#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
+ return retval;
+}
+
+asmlinkage int irix_ulimit(int cmd, int arg)
+{
+ switch(cmd) {
+ case 1:
+ printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 2:
+ printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 3:
+ printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ case 4:
+#if 0
+ printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
+ current->comm, current->pid);
+ return -EINVAL;
+#endif
+ return current->rlim[RLIMIT_NOFILE].rlim_cur;
+
+ case 5:
+ printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
+ current->comm, current->pid);
+ return -EINVAL;
+
+ default:
+ printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
+ current->comm, current->pid, cmd);
+ return -EINVAL;
+ }
+}
+
+asmlinkage int irix_unimp(struct pt_regs *regs)
+{
+ 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]);
+
+ return -ENOSYS;
+}
diff --git a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c
index d15aaa4dd..4aff0bc61 100644
--- a/arch/mips/kernel/sysmips.c
+++ b/arch/mips/kernel/sysmips.c
@@ -15,10 +15,9 @@
#include <linux/utsname.h>
#include <asm/cachectl.h>
-#include <asm/cache.h>
-#include <asm/ipc.h>
-#include <asm/uaccess.h>
+#include <asm/pgtable.h>
#include <asm/sysmips.h>
+#include <asm/uaccess.h>
static inline size_t
strnlen_user(const char *s, size_t count)
@@ -26,12 +25,35 @@ strnlen_user(const char *s, size_t count)
return strnlen(s, count);
}
+/*
+ * How long a hostname can we get from user space?
+ * -EFAULT if invalid area or too long
+ * 0 if ok
+ * >0 EFAULT after xx bytes
+ */
+static inline int
+get_max_hostname(unsigned long address)
+{
+ struct vm_area_struct * vma;
+
+ vma = find_vma(current->mm, address);
+ if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
+ return -EFAULT;
+ address = vma->vm_end - address;
+ if (address > PAGE_SIZE)
+ return 0;
+ if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
+ (vma->vm_next->vm_flags & VM_READ))
+ return 0;
+ return address;
+}
+
asmlinkage int
sys_sysmips(int cmd, int arg1, int arg2, int arg3)
{
int *p;
char *name;
- int flags, tmp, len, retval;
+ int flags, tmp, len, retval = -EINVAL;
switch(cmd)
{
@@ -39,70 +61,39 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
if (!suser())
return -EPERM;
name = (char *) arg1;
+ len = get_max_hostname((unsigned long)name);
+ if (retval < 0)
+ return len;
len = strnlen_user(name, retval);
- if (len < 0)
- retval = len;
- break;
if (len == 0 || len > __NEW_UTS_LEN)
- retval = -EINVAL;
- break;
+ return -EINVAL;
copy_from_user(system_utsname.nodename, name, len);
system_utsname.nodename[len] = '\0';
return 0;
-
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 = verify_area(VERIFY_WRITE, p, sizeof(*p));
- if (retval)
- return retval;
+ if(retval)
+ return -EINVAL;
save_flags(flags);
cli();
retval = *p;
*p = arg2;
restore_flags(flags);
- break;
-
+ return retval;
case MIPS_FIXADE:
tmp = current->tss.mflags & ~3;
current->tss.mflags = tmp | (arg1 & 3);
retval = 0;
break;
-
case FLUSH_CACHE:
- cacheflush(0, ~0, CF_BCACHE|CF_ALL);
- break;
-
- case MIPS_RDNVRAM:
- retval = -EIO;
- break;
-
- default:
- retval = -EINVAL;
+ flush_cache_all();
break;
}
return retval;
}
-asmlinkage int
-sys_cacheflush(void *addr, int nbytes, int cache)
-{
- unsigned int rw;
- int ok;
-
- if ((cache & ~(DCACHE | ICACHE)) != 0)
- return -EINVAL;
- rw = (cache & DCACHE) ? VERIFY_WRITE : VERIFY_READ;
- if (!access_ok(rw, addr, nbytes))
- return -EFAULT;
-
- cacheflush((unsigned long)addr, (unsigned long)nbytes, cache|CF_ALL);
-
- return 0;
-}
-
/*
* No implemented yet ...
*/
@@ -111,3 +102,36 @@ sys_cachectl(char *addr, int nbytes, int op)
{
return -ENOSYS;
}
+
+/* For emulation of various binary types, and their shared libs,
+ * we need this.
+ */
+
+extern int do_open_namei(const char *pathname, int flag, int mode,
+ struct inode **res_inode, struct inode *base);
+
+/* Only one at this time. */
+#define IRIX32_EMUL "/usr/gnemul/irix"
+
+int open_namei(const char *pathname, int flag, int mode,
+ struct inode **res_inode, struct inode *base)
+{
+ if(!base && (current->personality == PER_IRIX32) &&
+ *pathname == '/') {
+ struct inode *emul_ino;
+ const char *p = pathname;
+ char *emul_path = IRIX32_EMUL;
+ int v;
+
+ while (*p == '/')
+ p++;
+
+ if(do_open_namei (emul_path, flag, mode, &emul_ino, NULL) >= 0 &&
+ emul_ino) {
+ v = do_open_namei (p, flag, mode, res_inode, emul_ino);
+ if(v >= 0)
+ return v;
+ }
+ }
+ return do_open_namei (pathname, flag, mode, res_inode, base);
+}
diff --git a/arch/mips/kernel/tags.c b/arch/mips/kernel/tags.c
deleted file mode 100644
index 4bf480c54..000000000
--- a/arch/mips/kernel/tags.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * linux/arch/mips/kernel/tags.c
- *
- * Copyright (C) 1996 Stoned Elipot
- */
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.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/kernel/traps.c b/arch/mips/kernel/traps.c
index 0fb16f1a5..20cd6fe06 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -4,22 +4,35 @@
* 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.
+ */
+
+/*
+ * 'traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
+ * to mainly kill the offending process (probably by giving it a signal,
+ * but possibly by killing it outright if necessary).
+ *
+ * FIXME: This is the place for a fpu emulator.
*
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
- * Copyright (C) 1994, 1995, 1996 by Paul M. Antoine
+ * Modified for R3000 by Paul M. Antoine, 1995, 1996
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <asm/branch.h>
-#include <asm/cache.h>
+#include <asm/cachectl.h>
#include <asm/jazz.h>
#include <asm/vector.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/bootinfo.h>
-#include <asm/sgidefs.h>
-#include <asm/uaccess.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
@@ -38,9 +51,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);
@@ -51,11 +67,15 @@ extern asmlinkage void handle_ri(void);
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
+extern asmlinkage void handle_vcei(void);
extern asmlinkage void handle_fpe(void);
+extern asmlinkage void handle_vced(void);
extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_reserved(void);
-char *cpu_names[] = CPU_NAMES;
+static char *cpu_names[] = CPU_NAMES;
+unsigned long page_colour_mask;
unsigned int watch_available = 0;
void (*ibe_board_handler)(struct pt_regs *regs);
@@ -82,6 +102,7 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
/*
* Just return if in user mode.
+ * XXX
*/
#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
if (!((regs)->cp0_status & 0x4))
@@ -208,25 +229,26 @@ void do_fpe(struct pt_regs *regs, unsigned int fcr31)
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
{
- unsigned int *addr;
+ unsigned int *epc;
- addr = (unsigned int *) (unsigned long) regs->cp0_epc;
+ epc = (unsigned int *) (unsigned long) regs->cp0_epc;
if (regs->cp0_cause & CAUSEF_BD)
- addr += 4;
+ epc += 4;
- if (get_user(*opcode, addr)) {
+ if (verify_area(VERIFY_READ, epc, 4)) {
force_sig(SIGSEGV, current);
- return -EFAULT;
+ return 1;
}
+ *opcode = *epc;
return 0;
}
-static __inline__ void
+static inline void
do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode)
{
/*
- * (A quick test says that IRIX 5.3 sends SIGTRAP for all break
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
* insns, even for break codes that indicate arithmetic failures.
* Wiered ...)
*/
@@ -234,8 +256,6 @@ do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode)
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#endif
- if (compute_return_epc(regs))
- return;
}
void do_bp(struct pt_regs *regs)
@@ -247,11 +267,17 @@ void do_bp(struct pt_regs *regs)
* 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))
return;
bcode = ((opcode >> 16) & ((1 << 20) - 1));
do_bp_and_tr(regs, "bp", bcode);
+
+ if (compute_return_epc(regs))
+ return;
}
void do_tr(struct pt_regs *regs)
@@ -265,16 +291,13 @@ void do_tr(struct pt_regs *regs)
do_bp_and_tr(regs, "tr", bcode);
}
-/*
- * TODO: add emulation of higher ISAs' instruction. In particular
- * interest in MUL, MAD MADU has been expressed such that R4640/R4650
- * code can be run on other MIPS CPUs.
- */
void do_ri(struct pt_regs *regs)
{
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#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))
return;
force_sig(SIGILL, current);
@@ -285,11 +308,11 @@ void do_cpu(struct pt_regs *regs)
unsigned int cpid;
cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
- if (cpid == 1) {
+ if (cpid == 1)
+ {
regs->cp0_status |= ST0_CU1;
return;
}
-
force_sig(SIGILL, current);
}
@@ -349,8 +372,49 @@ static void watch_init(unsigned long cputype)
}
}
+typedef asmlinkage int (*syscall_t)(void *a0,...);
+asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg);
+extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs,
+ syscall_t fun, int narg);
+extern asmlinkage int r2300_do_syscalls(struct pt_regs *regs,
+ syscall_t fun, int narg);
+
+asmlinkage void (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc);
+extern asmlinkage void r2300_save_fp_context(struct sigcontext *sc);
+extern asmlinkage void r6000_save_fp_context(struct sigcontext *sc);
+
+asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage void r4k_restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage void r4xx0_resume(void *tsk);
+extern asmlinkage void r2300_resume(void *tsk);
+
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++)
+ set_except_vector(i, handle_reserved);
+
/*
* Only some CPUs have the watch exception.
*/
@@ -368,21 +432,55 @@ void trap_init(void)
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:
+ /* 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_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);
- case CPU_R4000MC: case CPU_R4400MC: case CPU_R4000SC:
- case CPU_R4400SC: case CPU_R4000PC: case CPU_R4400PC:
- case CPU_R4200: /*case CPU_R4300: case CPU_R4640: */
- case CPU_R4600: case CPU_R4700:
- set_except_vector(1, handle_mod);
- set_except_vector(2, handle_tlbl);
- set_except_vector(3, handle_tlbs);
+ /*
+ * The idea is that this special r4000 general exception
+ * vector will check for VCE exceptions before calling
+ * out of the exception array. XXX TODO
+ */
+ 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
@@ -398,11 +496,22 @@ void trap_init(void)
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
set_except_vector(15, handle_fpe);
- break;
- case CPU_R6000: case CPU_R6000A:
+ /*
+ * Compute mask for page_colour(). This is based on the
+ * 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
+ /*
+ * 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
@@ -411,22 +520,20 @@ void trap_init(void)
set_except_vector(14, handle_mc);
set_except_vector(15, handle_ndc);
#endif
- case CPU_R2000: case CPU_R3000: case CPU_R3000A: case CPU_R3041:
- case CPU_R3051: case CPU_R3052: case CPU_R3081: case CPU_R3081E:
- /*
- * Clear BEV, we are ready to handle exceptions using
- * the in-RAM dispatchers. This will not be useful on all
- * machines, but it can't hurt (the worst that can happen is
- * that BEV is already 0).
- */
- set_cp0_status(ST0_BEV,0);
-
+ case CPU_R2000:
+ case CPU_R3000:
+ case CPU_R3000A:
/*
* Actually don't know about these, but let's guess - PMA
*/
- set_except_vector(1, handle_mod);
- set_except_vector(2, handle_tlbl);
- set_except_vector(3, handle_tlbs);
+ 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);
/*
@@ -446,9 +553,27 @@ void trap_init(void)
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
set_except_vector(15, handle_fpe);
- break;
- case CPU_R8000: case CPU_R5000:
+ /*
+ * 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_R8000:
printk("Detected unsupported CPU type %s.\n",
cpu_names[mips_cputype]);
panic("Can't handle CPU");
@@ -456,6 +581,7 @@ void trap_init(void)
case CPU_UNKNOWN:
default:
- panic("Unsupported CPU type");
+ panic("Unknown CPU type");
}
+ flush_cache_all();
}
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 8bf2ad9b7..ba3a612fa 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -96,6 +96,8 @@
#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.
@@ -104,11 +106,11 @@
if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \
goto sigbus;
-static __inline__ void
+static inline void
emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long pc)
{
union mips_instruction insn;
- __register_t value;
+ register_t value;
regs->regs[0] = 0;
/*
@@ -369,7 +371,7 @@ sigbus:
unsigned long unaligned_instructions;
-static __inline__ void
+static inline void
fix_ade(struct pt_regs *regs, unsigned long pc)
{
/*
@@ -400,8 +402,8 @@ fix_ade(struct pt_regs *regs, unsigned long pc)
asmlinkage void
do_ade(struct pt_regs *regs)
{
- __register_t pc = regs->cp0_epc;
- __register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr;
+ register_t pc = regs->cp0_epc;
+ register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr;
char *adels;
adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >>
@@ -426,7 +428,7 @@ do_ade(struct pt_regs *regs)
#ifdef CONF_LOG_UNALIGNED_ACCESSES
if (current->tss.mflags & MF_LOGADE) {
- __register_t logpc = pc;
+ register_t logpc = pc;
if (regs->cp0_cause & CAUSEF_BD)
logpc += 4;
#ifdef __mips64
diff --git a/arch/mips/kernel/vm86.c b/arch/mips/kernel/vm86.c
index 53627201a..c0c775fba 100644
--- a/arch/mips/kernel/vm86.c
+++ b/arch/mips/kernel/vm86.c
@@ -1,15 +1,13 @@
/*
- * arch/mips/kernel/vm86.c
+ * arch/mips/vm86.c
*
- * Copyright (C) 1994, 1996 Waldorf GMBH,
+ * Copyright (C) 1994 Waldorf GMBH,
* written by Ralf Baechle
*/
#include <linux/linkage.h>
#include <linux/errno.h>
-struct vm86_struct;
-
-asmlinkage int sys_vm86(struct vm86_struct * v86)
+asmlinkage int sys_vm86(void *v86)
{
return -ENOSYS;
}
diff --git a/arch/mips/ld.script.big b/arch/mips/ld.script.big
new file mode 100644
index 000000000..88da74972
--- /dev/null
+++ b/arch/mips/ld.script.big
@@ -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 b/arch/mips/ld.script.little
index debe96282..26464d9f7 100644
--- a/arch/mips/ld.script
+++ b/arch/mips/ld.script.little
@@ -1,5 +1,4 @@
OUTPUT_FORMAT("elf32-littlemips")
-/* OUTPUT_FORMAT("a.out-mips-little-linux") */
OUTPUT_ARCH(mips)
ENTRY(kernel_entry)
SECTIONS
@@ -82,11 +81,11 @@ SECTIONS
*(.dynbss)
*(.bss)
*(COMMON)
+ _end = . ;
+ PROVIDE (end = .);
*(.sbss)
*(.scommon)
}
- _end = . ;
- PROVIDE (end = .);
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
diff --git a/arch/mips/lib/.cvsignore b/arch/mips/lib/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/lib/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index ac3cf45ad..0b2eec6d9 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -1,8 +1,8 @@
#
# Makefile for MIPS-specific library files..
#
-# Some of these routines are just left over debugging trash of ancient
-# times when I just could make my Tyne beep and so ...
+# Many of these routines are just left over debugging trash of ancient
+# times when I just make my Tyne beep and so ...
#
# ...and for when I need to get the DECStation to use the boot prom to
# do things... Paul M. Antoine.
@@ -14,9 +14,10 @@
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = lib.a
-L_OBJS = beep.o bitags.o checksum.o csum.o dump_tlb.o io.o memmove.o \
- strncpy_user.o strlen_user.o watch.o
-ifdef CONFIG_MIPS_DECSTATION
+L_OBJS = beep.o byteorder.o 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
diff --git a/arch/mips/lib/bcopy.c b/arch/mips/lib/bcopy.c
deleted file mode 100644
index 4afd557bf..000000000
--- a/arch/mips/lib/bcopy.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/mips/lib/bcopy.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
- * for more details.
- *
- * Copyright (c) 1994, 1995, 1996 by Ralf Baechle
- *
- * bcopy() only exists here such that it doesn't get compiled into
- * lib/strings.o. Though it's more efficient ...
- */
-#include <linux/string.h>
-
-char * bcopy(const char *src, char *dest, size_t count)
-{
- __memcpy(dest, src, count);
-
- return dest;
-}
diff --git a/arch/mips/lib/bitags.c b/arch/mips/lib/bitags.c
deleted file mode 100644
index 4427c4195..000000000
--- a/arch/mips/lib/bitags.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * milo/bitags.c -- handles the tags passed to the kernel
- *
- * Copyright (C) 1995 by Stoned Elipot <Stoned.Elipot@fnet.fr>
- * written by Stoned Elipot from an original idea of
- * Ralf Baechle <ralf@waldorf-gmbh.de>
- *
- * 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
- */
-#include <stdio.h>
-#include <asm/bootinfo.h>
-
-static unsigned int debuglevel = 0;
-
-extern unsigned long mach_mem_upper; /* from milo.c */
-extern unsigned long mach_mem_lower; /* from milo.c */
-
-static unsigned long next_tag = (unsigned long)NULL;
-
-/*
- * Create a tag
- *
- * Parameters: tag - tag type to create
- * size - tag's data size
- * tagdata - pointer on tag's data
- *
- * returns : 0 - success
- * 1 - failure
- */
-int
-bi_TagAdd(enum bi_tag type, unsigned long size, void *data)
-{
- tag t;
- unsigned long addr;
-
- t.tag = type;
- t.size = size;
- if (next_tag == (unsigned long)NULL) /* HuHo... first tag to create */
- {
- if (mach_mem_upper != (unsigned long)NULL) /* RAM detection code had run */
- {
- next_tag = mach_mem_upper;
- }
- else
- /* RAM dectection code had not run, let's hope the
- * tag we are creating is a memupper one, else fail
- * ...miserably, hopelessly, lonely
- */
- {
- if (type != tag_memupper)
- {
- return 1;
- }
- else
- {
- /*
- * saved, it's a memupper tag: put it's value in
- * mach_mem_upper so launch() can pass it to the kernel
- * in a0 and well we're going to create a tag anyway...
- */
- next_tag = *(unsigned long*)data;
- memcpy((void*)&mach_mem_upper, data, size);
- }
- }
- }
- addr = next_tag - (sizeof(tag));
- if (debuglevel >=2)
- {
- printk("bi_TagAdd: adding tag struct at %08x, tag: %d, size: %08x\r\n", addr, t.tag, t.size);
- }
- memcpy((void*)addr, (void*)&t, (size_t)(sizeof(tag)));
- if (size != 0)
- {
- addr = addr - size;
- if (debuglevel >=2)
- {
- printk("bi_TagAdd: adding tag value at %08x\r\n", addr);
- }
- memcpy((void*)addr, data, (size_t)(t.size));
- }
- next_tag = addr;
- return 0;
-}
-
-/*
- * Create tags from a "null-terminated" array of tag
- * (tag type of the tag_def struct in array must be 'dummy')
- *
- * Parameter: taglist - tag array pointer
- *
- * returns : 0 - success
- * 1 - failure
- */
-int
-bi_TagAddList(tag_def* taglist)
-{
- int ret_val = 0;
- for(; (taglist->t.tag != tag_dummy) && (!ret_val); taglist++)
- {
- /*
- * we assume this tag is present in the default taglist
- * for the machine we're running on
- */
- if (taglist->t.tag == tag_memlower)
- {
- mach_mem_lower = (unsigned long)(*((unsigned long*)taglist->d));
-/* ajouter detection de memupper pour simplifier le code de bi_TagAdd: soit mach_mem_upper
- a ete initialise par <machine_ident>() soit est initialise par le pre;ier tag de la list
- par default pour la machine */
- }
- ret_val = bi_TagAdd(taglist->t.tag, taglist->t.size, taglist->d);
- }
- return ret_val;
-}
-
-/*
- * 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
- *
- * Note: Just a 'prototype', the kernel's one is in
- * arch/mips/kernel/setup.c
- */
-/* tag* */
-/* bi_TagFind(enum bi_tag type) */
-/* { */
-/* tag* t; */
-/* t = (tag*)(mach_mem_upper - sizeof(tag)); */
-/* while((t->tag != tag_dummy) && (t->tag != type)) */
-/* t = (tag*)(NEXTTAGPTR(t)); */
-/* if (t->tag == tag_dummy) */
-/* { */
-/* return (tag*)NULL; */
-/* } */
-/* return t; */
-/* } */
-
-
-/*
- * Make a listing of tags available in memory: debug helper.
- */
-/* void */
-/* bi_TagWalk(void) */
-/* { */
-/* tag* t; */
-/* int i=0; */
-/* t = (tag*)(mach_mem_upper - sizeof(tag)); */
-/* while(t->tag != tag_dummy) */
-/* { */
-/* printk("tag #02%dm addr: %08x, type %d, size %u\n\r", i, (void*)t, t->tag, t->size); */
-/* t = (tag*)(NEXTTAGPTR(t)); */
-/* i++; */
-/* } */
-/* return; */
-/* } */
-
diff --git a/arch/mips/lib/byteorder.c b/arch/mips/lib/byteorder.c
new file mode 100644
index 000000000..188ed4b44
--- /dev/null
+++ b/arch/mips/lib/byteorder.c
@@ -0,0 +1,13 @@
+
+/*
+ * Library versions of the ntoh and hton functions. These are needed
+ * so that the address of the functions can be used.
+ *
+ * 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
+ */
+#define __EXTERN_INLINE
+#include <asm/byteorder.h>
diff --git a/arch/mips/lib/checksum.c b/arch/mips/lib/checksum.c
index 0e04ac5e8..dd1583892 100644
--- a/arch/mips/lib/checksum.c
+++ b/arch/mips/lib/checksum.c
@@ -17,124 +17,76 @@
#include <net/checksum.h>
#include <asm/string.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;
-
- /*
- * This is for 32-bit MIPS processors.
- */
- __asm__("
- .set noreorder
- .set noat
- andi $1,%4,2 # Check alignment
- beqz $1,2f # Branch if ok
- nop # delay slot
- subu $1,%3,2 # Alignment uses up two bytes
- bgez $1,1f # Jump if we had at least two bytes
- move %3,$1 # delay slot
- j 4f
- addiu %3,2 # delay slot; len was < 2. Deal with it
-
-1: lhu %2,(%4)
- addiu %4,2
- addu %0,%2
- sltu $1,%0,%2
- addu %0,$1
-
-2: srl %1,%3,5
- beqz %1,2f
- sll %1,%1,5 # delay slot
-
- addu %1,%4
-1: lw %2,0(%4)
- addu %4,32
- addu %0,%2
- sltu $1,%0,%2
+ unsigned long result = do_csum(buff, len);
- lw %2,-28(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-24(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-20(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-16(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-12(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-8(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- lw %2,-4(%4)
- addu %0,$1
- addu %0,%2
- sltu $1,%0,%2
-
- bne %4,%1,1b
- addu %0,$1 # delay slot
-
-2: andi %1,%3,0x1c
- beqz %1,4f
- addu %1,%4 # delay slot
-3: lw %2,0(%4)
- addu %4,4
- addu %0,%2
- sltu $1,%0,%2
- bne %4,%1,3b
- addu %0,$1 # delay slot
-
-4: andi $1,%3,3
- beqz $1,7f
- andi $1,%3,2 # delay slot
- beqz $1,5f
- move %2,$0 # delay slot
- lhu %2,(%4)
- addiu %4,2 # delay slot
-
-5: andi $1,%3,1
- beqz $1,6f
- nop # delay slot
- lbu %1,(%4)
- sll %2,16\n\t"
-#ifdef __MIPSEB__
- "sll %1,8\n\t"
-#endif
- "or %2,%1
-6: addu %0,%2
- sltu $1,%0,%2
- addu %0,$1
-7: .set at
- .set reorder"
- : "=r"(sum),
- "=&r" (scratch1),
- "=&r" (scratch2),
- "=r" (len),
- "=r" (buff)
- : "0"(sum), "3"(len), "4"(buff)
- : "$1");
-
- return sum;
+ /* add in old sum, and carry.. */
+ result += sum;
+ if(sum > result)
+ result += 1;
+ return result;
}
/*
@@ -144,12 +96,10 @@ unsigned int csum_partial_copy(const char *src, char *dst,
int len, unsigned int sum)
{
/*
- * It's 2:30 am and I don't feel like doing it right ...
+ * It's 2:30 am and I don't feel like doing it real ...
* This is lots slower than the real thing (tm)
*
* XXX This may nuke the kernel for unaligned src addresses!!!
- * (Due to software address error fixing no longer true, but
- * seems to happen very rarely only anyway.)
*/
sum = csum_partial(src, len, sum);
memcpy(dst, src, len);
diff --git a/arch/mips/mips1/memcpy.S b/arch/mips/lib/copy_user.S
index 9685fa8df..ea691f4fa 100644
--- a/arch/mips/mips1/memcpy.S
+++ b/arch/mips/lib/copy_user.S
@@ -18,7 +18,7 @@
#define EX(addr,handler) \
.section __ex_table,"a"; \
PTR addr, handler; \
- .text
+ .previous
#define UEX(addr,handler) \
EX(addr,handler); \
EX(addr+4,handler)
@@ -107,7 +107,7 @@ not_w_aligned:
andi v1,3
sltu t0,v0,v1
MOVN(v1,v0,t0)
- beqz v1,align4 # -> finished
+ beqz v1,3f # -> finished
LONG_ADDU v1,a0 # delay slot
1: lb $1,(a1)
EX(1b, fault)
@@ -119,6 +119,7 @@ not_w_aligned:
LONG_SUBU v0,1 # delay slot
b align4
nop # delay slot
+3:
/* ---------------------------------------------------------------------- */
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
index e7082e1ac..1ee4c79f0 100644
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -10,12 +10,12 @@
#include <linux/string.h>
#include <asm/bootinfo.h>
-#include <asm/cache.h>
+#include <asm/cachectl.h>
#include <asm/mipsconfig.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <asm/segment.h>
void
dump_tlb(int first, int last)
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
new file mode 100644
index 000000000..8039d21ae
--- /dev/null
+++ b/arch/mips/lib/memcpy.S
@@ -0,0 +1,222 @@
+/* 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>
+#include <asm/segment.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/memmove.c b/arch/mips/lib/memmove.c
deleted file mode 100644
index c3927ad49..000000000
--- a/arch/mips/lib/memmove.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * arch/mips/lib/memmove.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
- * for more details.
- *
- * Copyright (c) 1994, 1995, 1996 by Ralf Baechle
- *
- * Less stupid implementation of memmove.
- */
-#include <linux/string.h>
-
-void __memmove(void *dest, const void *src, size_t n)
-{
- if (!n)
- return;
-
- if (dest < src
- || dest > src + n)
- /* Copy forward */
- __memcpy(dest, src, n);
- else
- /* Copy backwards */
- __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" );
-}
diff --git a/arch/mips/lib/memset.c b/arch/mips/lib/memset.c
new file mode 100644
index 000000000..bbdbcbb31
--- /dev/null
+++ b/arch/mips/lib/memset.c
@@ -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/pmaxio.S b/arch/mips/lib/pmaxio.S
index 97ee46a23..66e216a55 100644
--- a/arch/mips/lib/pmaxio.S
+++ b/arch/mips/lib/pmaxio.S
@@ -1,5 +1,5 @@
#include <asm/regdef.h>
-#include <asm/dec/decstation.h>
+#include <asm/decstation.h>
.text
.set reorder
@@ -31,43 +31,6 @@ pmax_putch:
j v0
/*
- * pmax_callfn - call the PROM function
- */
- .globl pmax_callfn
-pmax_callfn:
- lw v0,pmax_rex_base
- addu v0,v0,a0
- lw v0,(v0)
- j v0
-
-/*
- * pmax_getbitmap - call the PROM for memory bitmap function
- */
- .globl pmax_getbitmap
-pmax_getbitmap:
- lw v0,pmax_rex_base
- lw v0,REX_GETBITMAP(v0)
- j v0
-
-/*
- * pmax_getgetenv - call the PROM to get environment variable
- */
- .globl pmax_getenv
-pmax_getenv:
- lw v0,pmax_rex_base
- lw v0,REX_GETENV(v0)
- j v0
-
-/*
- * pmax_getsysid - call the PROM to get system id
- */
- .globl pmax_getsysid
-pmax_getsysid:
- lw v0,pmax_rex_base
- lw v0,REX_GETSYSID(v0)
- j v0
-
-/*
* pmax_halt - call the PROM halt() function
*/
.globl pmax_halt
@@ -75,4 +38,3 @@ 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
index 3ef8ed18d..3569313ba 100644
--- a/arch/mips/lib/strlen_user.S
+++ b/arch/mips/lib/strlen_user.S
@@ -23,7 +23,7 @@ LEAF(__strlen_user)
LONG_ADDIU a0,1
bnez t0,1b
jr ra
- END(strlen_user)
+ END(__strlen_user)
.section __ex_table,"a"
PTR 1b,fault
diff --git a/arch/mips/lib/tags.c b/arch/mips/lib/tags.c
new file mode 100644
index 000000000..5425db712
--- /dev/null
+++ b/arch/mips/lib/tags.c
@@ -0,0 +1,74 @@
+/*
+ * linux/arch/mips/kernel/tags.c
+ *
+ * Copyright (C) 1996 Stoned Elipot
+ */
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.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
index 4b75dec20..ba25982df 100644
--- a/arch/mips/lib/tinycon.c
+++ b/arch/mips/lib/tinycon.c
@@ -33,12 +33,10 @@ extern struct screen_info screen_info;
void init_console(void)
{
size_x = 80;
- // size_y = 50;
size_y = 25;
cursor_x = 0;
cursor_y = 0;
- // vram_addr = (unsigned short *)0xe10b8000;
vram_addr = (unsigned short *)0xb00b8000;
console_needs_init = 0;
@@ -131,3 +129,5 @@ void print_string(const unsigned char *str)
break;
}
}
+
+/* end of file */
diff --git a/arch/mips/lib/watch.S b/arch/mips/lib/watch.S
index e460de6db..096375257 100644
--- a/arch/mips/lib/watch.S
+++ b/arch/mips/lib/watch.S
@@ -28,8 +28,9 @@
or a0,a1
mtc0 a0,CP0_WATCHLO
sw a0,watch_savelo
+
jr ra
- mtc0 zero,CP0_WATCHHI
+ mtc0 zero,CP0_WATCHHI
END(__watch_set)
/*
@@ -38,7 +39,7 @@
*/
LEAF(__watch_clear)
jr ra
- mtc0 zero,CP0_WATCHLO
+ mtc0 zero,CP0_WATCHLO
END(__watch_clear)
/*
@@ -47,8 +48,9 @@
*/
LEAF(__watch_reenable)
lw t0,watch_savelo
+
jr ra
- mtc0 t0,CP0_WATCHLO
+ mtc0 t0,CP0_WATCHLO
END(__watch_reenable)
/*
@@ -69,7 +71,7 @@ watch_savelo: .word 0
*/
LEAF(get_sp)
jr ra
- move v0,sp
+ move v0,sp
END(get_sp)
/*
@@ -78,7 +80,7 @@ watch_savelo: .word 0
*/
LEAF(get_ra)
jr ra
- move v0,ra
+ move v0,ra
END(get_ra)
/*
@@ -87,7 +89,7 @@ watch_savelo: .word 0
*/
LEAF(get_status)
jr ra
- mfc0 v0,CP0_STATUS
+ mfc0 v0,CP0_STATUS
END(get_status)
/*
@@ -101,8 +103,9 @@ watch_savelo: .word 0
move a1,sp
PRINT("$sp == %08lx\n")
REG_L ra,4*SZREG(sp)
+
jr ra
- PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK
+ PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK
END(print_sp)
/*
@@ -116,6 +119,7 @@ watch_savelo: .word 0
mfc0 a1,CP0_STATUS
PRINT("cp0_status == %08lx\n")
REG_L ra,4*SZREG(sp)
+
jr ra
- PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK
+ PTR_ADDU sp,((5*SZREG)+ALSZ)&ALMASK
END(print_st)
diff --git a/arch/mips/man/man8/hardware.8 b/arch/mips/man/man8/hardware.8
index b19e2d4e0..46b519f69 100644
--- a/arch/mips/man/man8/hardware.8
+++ b/arch/mips/man/man8/hardware.8
@@ -20,7 +20,7 @@
.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
.\" USA.
.\"
-.TH HARDWARE 8 "29 May 96" "Linux" "Supported hardware"
+.TH HARDWARE 8 "12 May 96" "Linux" "Supported hardware"
.SH ABSTRACT
This file contains information about the status of hardware support
@@ -29,14 +29,14 @@ of the various ports of Linux/MIPS.
.TP
.B "Acer PICA 61"
Supported; the onboard S3 graphics is fully supported in the
- text mode as well as the parallel port and the floppy (buggy). There
- are no drivers available yet for the onboard Ethernet interface and
- SCSI controller. However 35c03 Ethernet cards are working in PIO mode
- after disabeling the shared memory detection code, IDE harddisk and
- CD ROM have been successfully tested as well as NE2000 Ethernet cards
- and the DPT PM2041W ISA SCSI hostadapter (drivers EATA-DMA and
- EATA-PIO). In general all drivers that do PIO via ports are supposed
- to work.
+ text mode as well as the onboard Ethernet interface, the parallel
+ port and the floppy (buggy). There is no drivers available yet for
+ the onboard SCSI controller. However 35c03 Ethernet cards are
+ working in PIO mode after disabeling the shared memory detection code,
+ IDE harddisk and CD ROM have been successfully tested as well as
+ NE2000 Ethernet cards and the DPT PM2041W ISA SCSI hostadapter
+ (drivers EATA-DMA and EATA-PIO). In general all drivers that do PIO
+ via ports are supposed to work.
.TP
.B "Mips Magnum 4000"
Same status as Acer PICA 61; additionally the serial interface is
@@ -56,12 +56,12 @@ of the various ports of Linux/MIPS.
.TP
.B "SNI RM 200"
- Current status is that the ARC bootloader Milo is now also working
- on the unusually bahaving SNI ARC BIOS 4.05 (which is supposed to
- be the current version as of this writing); the kernel itself
- supports the builtin VGA card and floppy controller. It boots via
- an ISA NE2000 card from NFS; ISA DPT hostadapters have also
- successfully been tested. Other SNI hardware isn't supported yet.
+ This port has just started (10 May 1996). Current status is that
+ the ARC bootloader Milo is now also working on the (buggy) SNI
+ ARC BIOS 4.05 (which is supposed to be the current version as of
+ this writing); the kernel itself supports the builtin VGA card and
+ and boots via an ISA NE2000 card from NFS. Other SNI hardware
+ isn't supported yet.
.TP
.B "Deskstation Tyne"
@@ -77,11 +77,10 @@ of the various ports of Linux/MIPS.
.TP
.B "SGI"
- There is currently no port to SGI hardware; a port is about to
- start. Due to the resources SGI is willing to invest in this
- project this port will probably advance rather fast and help to
- improve Linux/MIPS in general so stay tuned. According to SGI
- also support of SMP machines is planned.
+ The SGI port was started at the end of May 1996 but has stalled
+ later in the year. Works have now been restarted. Currenly
+ the port supports only Indy machines and has a complete set of
+ drivers.
.TP
.B "DECstation"
diff --git a/arch/mips/mips1/Makefile b/arch/mips/mips1/Makefile
deleted file mode 100644
index 3e9f13037..000000000
--- a/arch/mips/mips1/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Makefile for the MIPS I specific parts of the Linux/MIPS kernel.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-.S.s:
- $(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
- $(CC) $(CFLAGS) -c $< -o $*.o
-
-all: mips.o
-EXTRA_ASFLAGS = -mips1 -mcpu=r3000
-O_TARGET := mips.o
-O_OBJS := cache.o cpu.o memcpy.o memset.o r3000.o pagetables.o showregs.o
- fp-context.o
-
-r3000.o: r3000.S
-
-fp-context.o: fp-context.S
-
-cache.o: cache.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips1/cache.S b/arch/mips/mips1/cache.S
deleted file mode 100644
index 788a567e8..000000000
--- a/arch/mips/mips1/cache.S
+++ /dev/null
@@ -1,162 +0,0 @@
-# R3000 cache routines lifted from IDT documentation
-# by Ruud Riem-Viis. Adapted for linux by Didier Frick
-# (dfrick@dial.eunet.ch)
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/processor.h>
-#include <asm/regdef.h>
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-#include <asm/stackframe.h>
-#include <asm/bootinfo.h>
-
-#define MINCACHE 0x00200 /* minimum cache size 512 */
-#define MAXCACHE 0x04000 /* maximum cache size 16K */
-
-/*
- * Figure out the size of the I- and D-caches, using the diagnostic isolate
- * swap features. The cache size is left in an environment variable because
- * the system will want to know it later.
- * Flush the cache so that it is in a known state.
- */
-NESTED(cache_init,8,ra)
- subu sp, sp, 24 # keep sp aligned on 8 words
- sw ra, 20(sp) # push return address on stack
- sw s0, 16(sp) # save s0 on stack
- mfc0 s0, CP0_STATUS # save sr
- mtc0 zero, CP0_STATUS
- nop
- .set reorder
- jal cache_size
- sw v0, mips_dcache_size
- li v0, ST0_CE # swap caches
- .set noreorder
- mtc0 v0, CP0_STATUS
- nop
- jal cache_size
- nop
- sw v0, mips_icache_size
- mtc0 zero, CP0_STATUS # swap back caches
- nop
- mtc0 s0, CP0_STATUS # restore sr
- nop
- .set reorder
- jal cache_flush
- lw s0, 16(sp) # restore s0
- lw ra, 20(sp)
- addu sp, sp, 24
- j ra
- nop
-END(cache_init)
-
-LEAF(cache_size)
- .set noreorder
- mfc0 t0, CP0_STATUS # save current SR
- nop
- and t0, ~ST0_SR # do not clear parity error bit
- or v0, t0, ST0_DE # isolate cache
- mtc0 v0, CP0_STATUS
- nop
-
- move v0, zero
- li v1, 0xa5a5a5a5
- nop
- sw v1, KSEG0 # try to write in cache
- lw t1, KSEG0 # try to read from cache
- nop
- mfc0 t2, CP0_STATUS
- nop
- .set reorder
- and t2, (1<<19)
- bne t2, zero, 3f # cache miss, must be no cache
- bne v1, t1, 3f # data not equal -> no cache
-
-/*
- * Clear cache boundries to known state.
- */
- li v0, MINCACHE
-1:
- sw zero, KSEG0(v0)
- sll v0, 1
- ble v0, MAXCACHE, 1b
-
- li v0, -1
- sw v0, KSEG0(zero) # store marker in cache
- li v0, MINCACHE # MIN cache size
-2:
- lw v1, KSEG0(v0) # look for marker
- bne v1, zero, 3f # found marker
- sll v0, 1 # cache size * 2
- ble v0, MAXCACHE, 2b # keep looking
- move v0, zero # must be no cache
- .set noreorder
-3:
- mtc0 t0, CP0_STATUS # restore sr
- nop
- j ra
- nop
- .set reorder
-END(cache_size)
-
-LEAF(cache_flush)
- lw t1, mips_icache_size
- lw t2, mips_dcache_size
- .set noreorder
- mfc0 t3, CP0_STATUS # save sr
- nop
- and t3, ~ST0_SR # do not clear PE
- beq t1, zero, check_dcache # if no icache, check dcache
- nop
- li v0, ST0_DE | ST0_CE # isolate and swap
- nop
- mtc0 v0, CP0_STATUS
- nop
- li t0, KSEG0
- .set reorder
- or t1, t0, t1
-1:
- sb zero, 0(t0)
- sb zero, 4(t0)
- sb zero, 8(t0)
- sb zero, 12(t0)
- sb zero, 16(t0)
- sb zero, 20(t0)
- sb zero, 24(t0)
- addu t0, 32
- sb zero, -4(t0)
- bne t0, t1, 1b # continue until done
-
-check_dcache:
- li v0, ST0_DE
- nop
- .set noreorder
- mtc0 v0, CP0_STATUS
- nop
- beq t2, zero, flush_done # if no dcache, done
- .set reorder
- li t0, KSEG0
- or t1, t0, t2
-1:
- sb zero, 0(t0)
- sb zero, 4(t0)
- sb zero, 8(t0)
- sb zero, 12(t0)
- sb zero, 16(t0)
- sb zero, 20(t0)
- sb zero, 24(t0)
- addu t0, 32
- sb zero, -4(t0)
- bne t0, t1, 1b # continue until done
-
- .set noreorder
-flush_done:
- mtc0 t3, CP0_STATUS # restore old sr
- nop
- j ra
- nop
- .set reorder
-END(cache_flush)
-
-
diff --git a/arch/mips/mips1/cpu.c b/arch/mips/mips1/cpu.c
deleted file mode 100644
index fd41ce15b..000000000
--- a/arch/mips/mips1/cpu.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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
- */
-#include <linux/sched.h>
-
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-
-extern asmlinkage void mips1_cacheflush(void *addr, int nbytes, unsigned int flags);
-
-void (*mips_cache_init)(void);
-
-static void
-mips1_cache_init(void)
-{
- cacheflush = mips1_cacheflush;
-}
-
-void (*switch_to_user_mode)(struct pt_regs *regs);
-
-static void
-mips1_switch_to_user_mode(struct pt_regs *regs)
-{
- regs->cp0_status = regs->cp0_status | ST0_KUC;
-}
-
-unsigned long (*thread_saved_pc)(struct thread_struct *t);
-
-/*
- * Return saved PC of a blocked thread.
- */
-static unsigned long mips1_thread_saved_pc(struct thread_struct *t)
-{
- return ((unsigned long *)(unsigned long)t->reg29)[13];
-}
-
-unsigned long (*get_wchan)(struct task_struct *p);
-
-static unsigned long mips1_get_wchan(struct task_struct *p)
-{
- /*
- * This one depends on the frame size of schedule(). Do a
- * "disass schedule" in gdb to find the frame size. Also, the
- * code assumes that sleep_on() follows immediately after
- * interruptible_sleep_on() and that add_timer() follows
- * immediately after interruptible_sleep(). Ugly, isn't it?
- * Maybe adding a wchan field to task_struct would be better,
- * after all...
- */
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long *)(long)p->tss.reg30)[13];
- return ((unsigned long *)schedule_frame)[11];
- }
- return pc;
-}
-
-void (*pgd_init)(unsigned long page);
-void (*copy_page)(unsigned long to, unsigned long from);
-asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
-
-void
-mips1_cpu_init(void)
-{
- extern void mips1_cache_init(void);
- extern void mips1_pgd_init(unsigned long page);
- extern void mips1_clear_page(unsigned long page);
- extern void mips1_copy_page(unsigned long to, unsigned long from);
- extern asmlinkage void mips1_restore_fp_context(struct sigcontext *sc);
- extern asmlinkage void mips1_save_fp_context(struct sigcontext *sc);
-
- mips_cache_init = mips1_cache_init;
- pgd_init = mips1_pgd_init;
- switch_to_user_mode = mips1_switch_to_user_mode;
- thread_saved_pc = mips1_thread_saved_pc;
- get_wchan = mips1_get_wchan;
- clear_page = mips1_clear_page;
- copy_page = mips1_copy_page;
- restore_fp_context = mips1_restore_fp_context;
- save_fp_context = mips1_save_fp_context;
-}
diff --git a/arch/mips/mips1/fp-context.S b/arch/mips/mips1/fp-context.S
deleted file mode 100644
index 6ff3c6be3..000000000
--- a/arch/mips/mips1/fp-context.S
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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
- */
-#include <asm/asm.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sigcontext.h>
-
-#define SWC1(r,m) \
-7: swc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define SW(r,m) \
-7: sw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LWC1(r,m) \
-7: lwc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LW(r,m) \
-7: lw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
- .set noreorder
-/*
- * Save floating point context
- */
-LEAF(mips1_save_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
- bgez t0,1f
- nop # delay slot
- 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) # delay slot
- .set macro
-
-1: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips1_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(mips1_restore_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
- bgez t0,1f
- nop # delay slot
- bgez t0,1f
- LW (t0,SC_FPC_CSR(a0)) # delay slot
- /*
- * Restore the 16 odd double precision registers only
- * when enabled in the cp0 status register.
- */
- LWC1 ($f0,(SC_FPREGS+0)(a0))
- LWC1 ($f1,(SC_FPREGS+8)(a0))
- LWC1 ($f2,(SC_FPREGS+16)(a0))
- LWC1 ($f3,(SC_FPREGS+24)(a0))
- LWC1 ($f4,(SC_FPREGS+32)(a0))
- LWC1 ($f5,(SC_FPREGS+40)(a0))
- LWC1 ($f6,(SC_FPREGS+48)(a0))
- LWC1 ($f7,(SC_FPREGS+56)(a0))
- LWC1 ($f8,(SC_FPREGS+64)(a0))
- LWC1 ($f9,(SC_FPREGS+72)(a0))
- LWC1 ($f10,(SC_FPREGS+80)(a0))
- LWC1 ($f11,(SC_FPREGS+88)(a0))
- LWC1 ($f12,(SC_FPREGS+96)(a0))
- LWC1 ($f13,(SC_FPREGS+104)(a0))
- LWC1 ($f14,(SC_FPREGS+112)(a0))
- LWC1 ($f15,(SC_FPREGS+120)(a0))
- LWC1 ($f16,(SC_FPREGS+128)(a0))
- LWC1 ($f17,(SC_FPREGS+136)(a0))
- LWC1 ($f18,(SC_FPREGS+144)(a0))
- LWC1 ($f19,(SC_FPREGS+152)(a0))
- LWC1 ($f20,(SC_FPREGS+160)(a0))
- LWC1 ($f21,(SC_FPREGS+168)(a0))
- LWC1 ($f22,(SC_FPREGS+176)(a0))
- LWC1 ($f23,(SC_FPREGS+184)(a0))
- LWC1 ($f24,(SC_FPREGS+192)(a0))
- LWC1 ($f25,(SC_FPREGS+200)(a0))
- LWC1 ($f26,(SC_FPREGS+208)(a0))
- LWC1 ($f27,(SC_FPREGS+216)(a0))
- LWC1 ($f28,(SC_FPREGS+224)(a0))
- LWC1 ($f29,(SC_FPREGS+232)(a0))
- LWC1 ($f30,(SC_FPREGS+240)(a0))
- LWC1 ($f31,(SC_FPREGS+248)(a0))
- jr ra
- .set nomacro
- ctc1 t0,fcr31 # delay slot
- .set macro
-
-1: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips1_restore_fp_context)
diff --git a/arch/mips/mips1/memset.S b/arch/mips/mips1/memset.S
deleted file mode 100644
index 5cfb5d9a7..000000000
--- a/arch/mips/mips1/memset.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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
- *
- * Generic memset for all MIPS CPUs.
- * This is time critical. Hear it crying "optimize me" ...
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-
-LEAF(__generic_memset_b)
-__generic_memset_dw = __generic_memset_b
- .set noreorder
- beqz a2,2f
- LONG_ADDU a3,a0,a2
- .set reorder
- LONG_SUBU a3,1
-1: sb a1,(a0)
- .set noreorder
- bne a0,a3,1b
- LONG_ADDIU a0,1
- .set reorder
-2: jr ra
- END(__generic_memset_b)
diff --git a/arch/mips/mips1/pagetables.c b/arch/mips/mips1/pagetables.c
deleted file mode 100644
index 22419d1c9..000000000
--- a/arch/mips/mips1/pagetables.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 32 bit MIPS specific 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) 1996 Ralf Baechle
- */
-#include <linux/mm.h>
-#include <asm/cache.h>
-#include <asm/mipsconfig.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-void (*pgd_init)(unsigned long page);
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-void mips1_pgd_init(unsigned long page)
-{
- unsigned long dummy1, dummy2;
-
- /*
- * The plain and boring version for the R3000. No cache flushing
- * stuff is needed 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 /* - PAGE_OFFSET */ ) |
- _PAGE_TABLE),
- "0" (page),
- "1" (PAGE_SIZE/(sizeof(pmd_t)*8)));
-}
-
-void (*clear_page)(unsigned long page)
-
-/*
- * To do: cache magic ...
- */
-void mips1_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");
-}
-
-void (*copy_page)(unsigned long to, unsigned long from);
-
-void mips1_copy_page(unsigned long to, unsigned long from)
-{
- memcpy((void *) to,
- (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
-}
diff --git a/arch/mips/mips1/r3000.S b/arch/mips/mips1/r3000.S
deleted file mode 100644
index 25529d9a0..000000000
--- a/arch/mips/mips1/r3000.S
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * arch/mips/kernel/r3000.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics, 1996 Paul M. Antoine
- * Written by Ralf Baechle and Andreas Busse
- * Modified for R3000 by Paul M. Antoine
- *
- * Additional R3000 support by Didier Frick <dfrick@dial.eunet.ch>
- * for ACN S.A, Copyright (C) 1996 by ACN S.A
- *
- * This file contains most of the R3000/R3000A specific routines, which would
- * probably work on the R2000 (if anyone's interested!).
- *
- * This code is evil magic. Read appendix f (coprocessor 0 hazards) of
- * all R3000/MIPS manuals and think about that MIPS means "Microprocessor without
- * Interlocked Pipeline Stages" before you even think about changing this code!
- *
- * Then remember that some bugs here are due to my not having completely
- * converted the R4xx0 code to R3000 and that the R4xx0 CPU's are more
- * forgiving than the R3000/A!! All that, and the fact that I'm not up to
- * 'guru' level on R3000 - PMA.
- * (Paul, I replaced all occurances of TLBMAPHI with %HI(TLBMAP) -- Ralf)
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef __SMP__
-#error "Fix this for SMP!"
-#else
-#define current current_set
-#endif
-
-/*
-
-FIXME:
- - First of all, this really screams for a light version of SAVE_ALL
- and RESTORE_ALL, saving and restoring only the context actually
- needed in this case. I'm afraid it's necessary to save some context
- on the stack because on the R3000 tlb exceptions can nest in some
- cases where they wouldn't on the R4000.
-
- - The TLB handling code should be completely rewritten for the R3000
- because too many things are different from the R4000.
- For instance, the CP0_CONTEXT register has a different format
- and cannot be reused with the current setup.
- I really had to do a fast hack to get it to work, but no time to do
- it cleanly for now, sorry.
- We also introduced a tlb_softindex variable to point to the next
- TLB entry to write. This variable is incremented everytime we add a
- new entry to the TLB. We did this because we felt that using the
- CP0_RANDOM register could be unsafe in some cases (like trashing
- the TLB entry for the handler's return address in user space).
- It's very possible that we are wrong on this one, but we had so
- much trouble with this TLB thing that we chose the safe side.
-*/
-
-#define CONF_DEBUG_TLB
-#undef CONFIG_TLB_SHUTDOWN
-#undef TLB_LOG
-
-MODE_ALIAS = 0x00e0 # cachable
-
- .text
- .set mips1
- .set noreorder
-
- .align 5
- NESTED(handle_tlbl, FR_SIZE, sp)
- .set noat
- /*
- * Check whether this is a refill or an invalid exception
- */
- mfc0 k0,CP0_BADVADDR
- nop
- 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
- nop
- mtc0 k0,CP0_ENTRYHI
- nop # for pipeline
- tlbp
- nop # for pipeline
- mfc0 k0,CP0_INDEX
- nop
- mtc0 k1,CP0_ENTRYHI # delay slot
- bgez k0,invalid_tlbl # bad addr in c0_badvaddr
- nop
-
-
- mfc0 k0,CP0_BADVADDR
- lui k1,0xe000
- subu k0,k0,k1
- bgez k0,1f
- nop
- j real_utlb
- nop
-
-1:
-
-
-#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.
- */
-
- lw k0, tlbl_lock
- nop
- bnez k0,1f
- li k1,1
- la k0, tlbl_lock
- sw k1,(k0)
-
-
- mfc0 k0,CP0_BADVADDR
- lui k1,58368
- srl k0,12 # get PFN?
- sll k0,2
- addu k0,k1
- lw k1,(k0)
- nop
- andi k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
- bnez k1,reload_pgd_entries
- nop # delay slot
-
-1:
- SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
-
- PRINT("Double fault caused by invalid entries in pgd:\n")
- mfc0 a1,CP0_BADVADDR
- nop
- PRINT("Double fault address : %08lx\n")
- mfc0 a1,CP0_EPC
- nop
- 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 k0,CP0_BADVADDR
- nop
- lui k1,58368
-
- srl k0,12
- sll k0,2
- addu k0,k1
- lw k0,(k0)
- nop
- mtc0 k0,CP0_ENTRYLO0
-
- la k0, tlb_softIndex
- lw k1,(k0)
- nop
- mtc0 k1,CP0_INDEX
- nop
- addu k1,(1<<8)
- andi k0,k1,(63<<8)
- bnez k0, 1f
- nop
- li k1,(8<<8)
-1:
- la k0, tlb_softIndex
- sw k1,(k0)
-
-
- nop
- nop
- nop # for pipeline
- tlbwi
- nop # for pipeline
- nop
- nop
-
-
-#ifdef CONF_DEBUG_TLB
- la k0, tlbl_lock
- sw zero,(k0)
-#endif
- mfc0 k0,CP0_EPC
- nop
- jr k0
- rfe
- nop
-
-
- /*
- * 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:
- SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
-
-#ifdef TLB_LOG
- PRINT ("tlbl: invalid\n");
- nop
-#endif
- /*
- * Test present bit in entry
- */
- lw s0,FR_BADVADDR(sp)
- nop
- srl s0,12
- sll s0,2
- lui k1,58368
- addu s0,k1
-
- lw k1,(s0)
- nop
- andi k1,(_PAGE_PRESENT|_PAGE_READ)
- xori k1,(_PAGE_PRESENT|_PAGE_READ)
- bnez k1,nopage_tlbl
- nop
- /*
- * Present and read bits are set -> set valid and accessed bits
- */
- lw k1,(s0) # delay slot
- nop
- ori k1,(_PAGE_VALID|_PAGE_ACCESSED)
- sw k1,(s0)
-
- mtc0 k1,CP0_ENTRYLO0
- nop
- tlbwi
- nop
- nop
-
- j return
- nop
-
- /*
- * 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 */
- REG_S sp,FR_ORIG_REG2(sp) */
-#ifdef TLB_LOG
- PRINT ("nopage_tlbl\n");
- nop
-#endif
-#ifdef CONFIG_TLB_SHUTDOWN
- mfc0 t0,CP0_INDEX
- sll t0,4
- la t1,KSEG1
- or t0,t1
- mtc0 t0,CP0_ENTRYHI
- mtc0 zero,CP0_ENTRYLO0
- nop
- nop
- tlbwi
- nop
- nop
-#endif
-
- lw a2,FR_BADVADDR(sp)
- li t1,-1 # not a sys call
- sw t1,FR_ORIG_REG2(sp)
- nop
- 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
- */
- /* used to be dmfc0 */
-
-#ifdef CONF_DEBUG_TLB
-
- la k0,tlbs_lock
- lw k1,(k0)
- nop
- beqz k1,3f
- nop
- .set noat
- SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
- .set at
- PRINT("Nested tlbs exception:\n")
- mfc0 a1,CP0_BADVADDR
- nop
- PRINT("Virtual address : %08lx\n")
- mfc0 a1,CP0_EPC
- nop
- 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("Nested tlbs exception")
-
-3:
- li k1,1
- sw k1,(k0)
-
-#endif
- .set noat
- SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
- .set at
-
- mfc0 s0,CP0_BADVADDR
-
- lui k1,58368
- srl s0,12
- sll s0,2
- addu s0,k1
- nop
- lw k1,(s0) # may cause nested xcpt.
- nop
- move k0,s0
-
- lw k1,FR_ENTRYHI(sp)
- nop
- mtc0 k1,CP0_ENTRYHI
- nop
- nop
- tlbp # find faulting entry
- nop
- lw k1,(k0)
- nop
- andi k1,(_PAGE_PRESENT|_PAGE_WRITE)
- xori k1,(_PAGE_PRESENT|_PAGE_WRITE)
- bnez k1,nopage_tlbs
- nop
- /*
- * Present and writable bits set: set accessed and dirty bits.
- */
- lw k1,(k0) # delay slot
- nop
- ori k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
- _PAGE_VALID|_PAGE_DIRTY)
- sw k1,(k0)
- /*
- * Now reload the entry into the TLB
- */
- mtc0 k1,CP0_ENTRYLO0
- nop
- nop
- nop # for pipeline
- tlbwi
- nop # for pipeline
-#ifdef CONF_DEBUG_TLB
- la k0,tlbs_lock
- li k1,0
- sw k1,(k0)
-#endif
- j return
- nop
-
- /*
- * 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.
- */
-nowrite_mod:
-nopage_tlbs:
-
-#ifdef CONFIG_TLB_SHUTDOWN
- /*
- * Remove entry so we don't need to care later
- */
- mfc0 k0,CP0_INDEX
- nop
-#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.
- */
- .set noat
-/* SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp) */
- jal show_regs
- move a0,sp
- .set at
- la a1,FR_BADVADDR(sp)
- lw a1,(a1)
- nop
- PRINT("c0_badvaddr == %08lx\n")
- nop
- mfc0 a1,CP0_INDEX
- nop
- PRINT("c0_index == %08x\n")
- nop
- la a1,FR_ENTRYHI(sp)
- lw a1,(a1)
- nop
- PRINT("c0_entryhi == %08x\n")
- nop
- jal dump_tlb_nonwired
- nop
- la a0,FR_BADVADDR(sp)
- lw a0,(a0)
- jal dump_list_current
- nop
-
- .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,0xa000
- sll k0,4
- or k0,k1
- xor k0,k1
- or k0,k1 # make it a KSEG1 address
- mtc0 k0,CP0_ENTRYHI
- nop
- mtc0 zero,CP0_ENTRYLO0
- nop
- nop
- nop
- tlbwi
- nop
-#endif /* CONFIG_TLB_SHUTDOWN */
-
-#ifdef CONF_DEBUG_TLB
- la k0,tlbs_lock
- li k1,0
- sw k1,(k0)
-#endif
- .set noat
-/* SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp) */
- lw a2,FR_BADVADDR(sp)
- li t1,-1
- sw t1,FR_ORIG_REG2(sp) # not a sys call
- nop
- 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
- */
- /* used to be dmfc0 */
-
- SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
-
- mfc0 s0,CP0_BADVADDR
- nop
-
- srl s0,12
- sll s0,2
- lui k1,58368
- addu s0,k1
- lw k1,(s0)
- nop
- move k0,s0
- nop
-
- lw k1,FR_ENTRYHI(sp)
- nop
- mtc0 k1,CP0_ENTRYHI
- nop
- tlbp
- nop
- lw k1,(k0)
- nop
- andi k1,_PAGE_WRITE
- beqz k1,nowrite_mod
- nop
- /*
- * Present and writable bits set: set accessed and dirty bits.
- */
- lw k1,(k0) # delay slot
- nop
- ori k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
- sw k1,(k0)
- /*
- * Now reload the entry into the tlb
- */
- lw k0,(k0)
- nop
- mtc0 k0,CP0_ENTRYLO0
- nop
- nop # for pipeline
- nop
- tlbwi
- nop # for pipeline
- j return
- nop
- END(handle_mod)
- .set at
-
- .set reorder
- LEAF(tlbflush)
-
- .set noreorder
-
- mfc0 t3,CP0_STATUS # disable interrupts...
- nop
- ori t4,t3,1
- xori t4,1
- mtc0 t4,CP0_STATUS
- lw t1,mips_tlb_entries /* mips_tlb_enbtries is set */
- /* by bi_EarlySnarf() */
- mfc0 t0,CP0_ENTRYHI
- nop
- mtc0 zero,CP0_ENTRYLO0
- sll t1,t1,8
- li t2,KSEG1
- li t5,(7<<8) /* R3000 has 8 wired entries */
-1:
- subu t1,(1<<8)
- beq t1,t5,2f /* preserve wired entries */
-
- sll t6,t1,4
- addu t6,t2
- mtc0 t6,CP0_ENTRYHI
- nop
- mtc0 t1,CP0_INDEX
- nop
- nop
- nop
- tlbwi
- nop
- b 1b
- nop
-2:
-
- mtc0 t0,CP0_ENTRYHI
- nop
- mtc0 t3,CP0_STATUS
- nop
- jr ra
- nop
- END(tlbflush)
-
-/*
- * Flush a single entry from the TLB
- *
- * Parameters: a0 - unsigned long address
- */
- .set noreorder
- LEAF(tlbflush_page)
- /*
- * Step 1: Wipe out old TLB information. Not shure if
- * we really need that step; call it paranoia ...
- * In order to do that we need to disable interrupts.
- */
- mfc0 t0,CP0_STATUS # interrupts off
- nop
- ori t1,t0,1
- xori t1,1
- mtc0 t1,CP0_STATUS
- li t3,TLBMAP # then wait 3 cycles
- ori t1,a0,0xfff # mask off low 12 bits
- xori t1,0xfff
- mfc0 t2,CP0_ENTRYHI # copy ASID into address
- nop
- andi t2,0xfc0 # ASID in bits 11-6
- or t2,t1
- mtc0 t2,CP0_ENTRYHI
-/* FIXME:
- shouldn't we save ENTRYHI before trashing it ?
-*/
-
- srl t4,a0,12 # wait again three cycles
- sll t4,t4,PTRLOG
- mtc0 zero,CP0_ENTRYLO0
- nop
- tlbp # now query the TLB
- addu t3,t4 # wait another three cycles
- ori t3,0xffff
- xori t3,0xffff
- mfc0 t1,CP0_INDEX
- nop
- blez t1,1f # No old entry?
- nop # delay slot
- li t5, KSEG1
- sll t1,4
- addu t5,t1
- mtc0 t5,CP0_ENTRYHI
- nop
- nop
- 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
- nop
- blez t1,1f # No old entry?
- nop
- li t5, KSEG1
- sll t1,4
- addu t5,t1
- mtc0 t5,CP0_ENTRYHI
- nop
- nop
- tlbwi # gotcha ...
- nop
- nop
- nop
-
-1:
- mtc0 t0,CP0_STATUS
- nop
- jr ra
- nop
-
- END(tlbflush_page)
-
- .set noreorder
- LEAF(tlbload)
- /*
- address in a0
- pte in a1
- */
-
- mfc0 t1,CP0_STATUS
- nop
- ori t0,t1,1
- xori t0,1
- mtc0 t0,CP0_STATUS
- nop
- mfc0 t0,CP0_ENTRYHI
- nop
- ori a0,0xfff
- xori a0,0xfff
- andi t2,t0,0xfc0
- or a0,t2
- mtc0 a0,CP0_ENTRYHI
- nop
- nop
- mtc0 a1,CP0_ENTRYLO0
-
- la t2, tlb_softIndex
- lw t3,(t2)
- nop
- mtc0 t3, CP0_INDEX
- nop
- addu t3,(1<<8)
- andi t2,t3,(63<<8)
- bnez t2, 1f
- nop
- li t3,(8<<8)
-1:
- la t2, tlb_softIndex
- sw t3,(t2)
-
-
- nop
- nop
- nop
- tlbwi
- nop
- nop
- mtc0 t0,CP0_ENTRYHI
- nop
- mtc0 t1,CP0_STATUS
-
- jr ra
- nop
-
- END(tlbload)
-
-
-
-/*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- * FIXME: We don't need to disable interrupts anymore.
- */
- .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)
-
-/*
- li t2,ST0_CU0
- and t2,t1
- beqz t2,1f
- nop
- sw sp,TOFF_KSP(t0)
-1:
-*/
- /*
- * Disable interrupts
- */
-#ifndef __R3000__
- ori t2,t1,0x1f
- xori t2,0x1e
-#else
- ori t2,t1,1
- xori t2,1
-#endif
- 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
- swc1 $f0,(TOFF_FPU+0)(t0) # delay slot
- /*
- * Store the 16 odd double precision registers
- */
- swc1 $f1,(TOFF_FPU+8)(t0)
- swc1 $f3,(TOFF_FPU+24)(t0)
- swc1 $f5,(TOFF_FPU+40)(t0)
- swc1 $f7,(TOFF_FPU+56)(t0)
- swc1 $f9,(TOFF_FPU+72)(t0)
- swc1 $f11,(TOFF_FPU+88)(t0)
- swc1 $f13,(TOFF_FPU+104)(t0)
- swc1 $f15,(TOFF_FPU+120)(t0)
- swc1 $f17,(TOFF_FPU+136)(t0)
- swc1 $f19,(TOFF_FPU+152)(t0)
- swc1 $f21,(TOFF_FPU+168)(t0)
- swc1 $f23,(TOFF_FPU+184)(t0)
- swc1 $f25,(TOFF_FPU+200)(t0)
- swc1 $f27,(TOFF_FPU+216)(t0)
- swc1 $f29,(TOFF_FPU+232)(t0)
- swc1 $f31,(TOFF_FPU+248)(t0)
-
- /*
- * Store the 16 even double precision registers
- */
-1: cfc1 t1,fcr31
- swc1 $f2,(TOFF_FPU+16)(t0)
- swc1 $f4,(TOFF_FPU+32)(t0)
- swc1 $f6,(TOFF_FPU+48)(t0)
- swc1 $f8,(TOFF_FPU+64)(t0)
- swc1 $f10,(TOFF_FPU+80)(t0)
- swc1 $f12,(TOFF_FPU+96)(t0)
- swc1 $f14,(TOFF_FPU+112)(t0)
- swc1 $f16,(TOFF_FPU+128)(t0)
- swc1 $f18,(TOFF_FPU+144)(t0)
- swc1 $f20,(TOFF_FPU+160)(t0)
- swc1 $f22,(TOFF_FPU+176)(t0)
- swc1 $f24,(TOFF_FPU+192)(t0)
- swc1 $f26,(TOFF_FPU+208)(t0)
- swc1 $f28,(TOFF_FPU+224)(t0)
- swc1 $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) # get PFN
- li t1,TLB_ROOT
- mtc0 t1,CP0_ENTRYHI
- nop
- mtc0 zero,CP0_INDEX
- ori t0,MODE_ALIAS # want cachable, dirty, valid
- mtc0 t0,CP0_ENTRYLO0
- nop
- nop
- nop
- tlbwi # delay slot
- nop
-
- /*
- * Flush tlb
- * (probably not needed, doesn't clobber a0-a3)
- */
- jal tlbflush
- nop
-
- lw a2,TOFF_CP0_STATUS(a0)
- nop
-
- /*
- * 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
- nop
- lwc1 $f0,(TOFF_FPU+0)(a0) # delay slot
- /*
- * Restore the 16 odd double precision registers only
- * when enabled in the cp0 status register.
- */
- lwc1 $f1,(TOFF_FPU+8)(a0)
- lwc1 $f3,(TOFF_FPU+24)(a0)
- lwc1 $f5,(TOFF_FPU+40)(a0)
- lwc1 $f7,(TOFF_FPU+56)(a0)
- lwc1 $f9,(TOFF_FPU+72)(a0)
- lwc1 $f11,(TOFF_FPU+88)(a0)
- lwc1 $f13,(TOFF_FPU+104)(a0)
- lwc1 $f15,(TOFF_FPU+120)(a0)
- lwc1 $f17,(TOFF_FPU+136)(a0)
- lwc1 $f19,(TOFF_FPU+152)(a0)
- lwc1 $f21,(TOFF_FPU+168)(a0)
- lwc1 $f23,(TOFF_FPU+184)(a0)
- lwc1 $f25,(TOFF_FPU+200)(a0)
- lwc1 $f27,(TOFF_FPU+216)(a0)
- lwc1 $f29,(TOFF_FPU+232)(a0)
- lwc1 $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)
- lwc1 $f2,(TOFF_FPU+16)(a0)
- lwc1 $f4,(TOFF_FPU+32)(a0)
- lwc1 $f6,(TOFF_FPU+48)(a0)
- lwc1 $f8,(TOFF_FPU+64)(a0)
- lwc1 $f10,(TOFF_FPU+80)(a0)
- lwc1 $f12,(TOFF_FPU+96)(a0)
- lwc1 $f14,(TOFF_FPU+112)(a0)
- lwc1 $f16,(TOFF_FPU+128)(a0)
- lwc1 $f18,(TOFF_FPU+144)(a0)
- lwc1 $f20,(TOFF_FPU+160)(a0)
- lwc1 $f22,(TOFF_FPU+176)(a0)
- lwc1 $f24,(TOFF_FPU+192)(a0)
- lwc1 $f26,(TOFF_FPU+208)(a0)
- lwc1 $f28,(TOFF_FPU+224)(a0)
- lwc1 $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)
- nop
- sw t0,kernelsp
-
- mtc0 a2,CP0_STATUS # delay slot
- jr ra
- nop
- END(resume)
-
- /*
- * Load a new root pointer into the tlb
- */
- .set noreorder
- LEAF(load_pgd)
- /*
- * Switch the root pointer
- */
- mfc0 t0,CP0_STATUS
- nop
- ori t1,t0,1
- xori t1,1
- mtc0 t1,CP0_STATUS
-
- ori a0,MODE_ALIAS
- li t1,TLB_ROOT
- mtc0 t1,CP0_ENTRYHI
- nop
- mtc0 zero,CP0_INDEX
- nop
- mtc0 a0,CP0_ENTRYLO0
- nop
- nop
- nop
- tlbwi
- nop
- nop
- mtc0 t0,CP0_STATUS
- nop
- jr ra
- nop
- END(load_pgd)
-
-/*
- * Some bits in the config register
- */
-#define CONFIG_DB (1<<4)
-#define CONFIG_IB (1<<5)
-
-/*
- * Flush instruction/data caches - FIXME: Don't know how to do this on R[236]000!
- * (Actually most of this flushing stuff isn't needed for the R2000/R3000/R6000
- * since these CPUs have physical indexed caches unlike R4000 and better
- * which have virtual indexed 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(mips1_cacheflush)
-
-done: j cache_flush
- nop
- END(mips1_cacheflush)
-
-/*
- * Invalidate virtual addresses. - FIXME: Don't know how on R[236]000 yet!
- * (Flushing is relativly expensive; it isn't required at all if a
- * particular machines' chipset keeps the external cache in a state that is
- * consistent with memory -- Ralf)
- *
- * Parameters: a0 - starting address to flush
- * a1 - size of area to be flushed
- *
- * FIXME: - ignores parameters in a0/a1
- * - doesn't know about second level caches
- */
- .set noreorder
- LEAF(fd_cacheflush)
- jr ra
- nop
- END(fd_cacheflush)
-
-/*
- * 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 reorder
- .text
-NESTED(do_syscalls, 32, sp)
- subu sp,32
- sw ra,28(sp)
- sll a2,a2,PTRLOG
- lw t1,dst(a2)
- move t2,a1
- lw t0,FR_REG29(a0) # get old user stack pointer
- jalr t1
-
-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,FR_REG7(a0) # 4 args
-3: lw a2,FR_REG6(a0) # 3 args
-2: lw a1,FR_REG5(a0) # 2 args
-1: lw a0,FR_REG4(a0) # delay slot
- jalr t2 # 1 args
- 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)
-
- .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
-
- .data
-
- EXPORT(tlbl_lock)
- .word 0
-
-tlbs_lock:
- .word 0
-
- EXPORT(tlb_softIndex)
- .word 0
diff --git a/arch/mips/mips1/showregs.c b/arch/mips/mips1/showregs.c
deleted file mode 100644
index 0be6db80e..000000000
--- a/arch/mips/mips1/showregs.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * linux/arch/mips/mips1/showregs.c
- *
- * Copyright (C) 1995, 1996 Ralf Baechle, Paul M. Antoine.
- */
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-void show_regs(struct pt_regs * regs)
-{
- /*
- * Saved main processor registers
- */
- printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- 0, regs->regs[1], regs->regs[2], regs->regs[3],
- regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11],
- regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19],
- regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[24], regs->regs[25], regs->regs[28], regs->regs[29],
- regs->regs[30], regs->regs[31]);
-
- /*
- * Saved cp0 registers
- */
- printk("epc : %08lx\nStatus: %08x\nCause : %08x\nBadVAdddr : %08x\n",
- regs->cp0_epc, regs->cp0_status, regs->cp0_cause,regs->cp0_badvaddr);
-}
diff --git a/arch/mips/mips2/Makefile b/arch/mips/mips2/Makefile
deleted file mode 100644
index 1d53d027c..000000000
--- a/arch/mips/mips2/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the MIPS II specific parts of the Linux/MIPS kernel.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-.S.s:
- $(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
- $(CC) $(CFLAGS) -c $< -o $*.o
-
-all: mips.o
-EXTRA_ASFLAGS = -mips2 -mcpu=r6000
-O_TARGET := mips.o
-O_OBJS := cpu.o pagetables.o showregs.o
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips2/README b/arch/mips/mips2/README
deleted file mode 100644
index c64808874..000000000
--- a/arch/mips/mips2/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory contains the R6000 specific part. I (Ralf) tried to support
-this CPU as good as possible without a machine and without detailed
-documentation. So don't look to close on this part ...
diff --git a/arch/mips/mips2/cpu.c b/arch/mips/mips2/cpu.c
deleted file mode 100644
index bcc021ee7..000000000
--- a/arch/mips/mips2/cpu.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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
- */
-#include <linux/sched.h>
-
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-
-extern asmlinkage void mips2_cacheflush(void *addr, int nbytes, unsigned int flags);
-
-void (*mips_cache_init)(void);
-
-static void
-mips2_cache_init(void)
-{
- cacheflush = mips2_cacheflush;
-}
-
-void (*switch_to_user_mode)(struct pt_regs *regs);
-
-static void
-mips2_switch_to_user_mode(struct pt_regs *regs)
-{
- regs->cp0_status = regs->cp0_status | ST0_KUC;
-}
-
-unsigned long (*thread_saved_pc)(struct thread_struct *t);
-
-/*
- * Return saved PC of a blocked thread.
- */
-static unsigned long mips2_thread_saved_pc(struct thread_struct *t)
-{
- return ((unsigned long *)(unsigned long)t->reg29)[13];
-}
-
-unsigned long (*get_wchan)(struct task_struct *p);
-
-static unsigned long mips2_get_wchan(struct task_struct *p)
-{
- /*
- * This one depends on the frame size of schedule(). Do a
- * "disass schedule" in gdb to find the frame size. Also, the
- * code assumes that sleep_on() follows immediately after
- * interruptible_sleep_on() and that add_timer() follows
- * immediately after interruptible_sleep(). Ugly, isn't it?
- * Maybe adding a wchan field to task_struct would be better,
- * after all...
- */
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long *)(long)p->tss.reg30)[13];
- return ((unsigned long *)schedule_frame)[11];
- }
- return pc;
-}
-
-void (*pgd_init)(unsigned long page);
-void (*copy_page)(unsigned long to, unsigned long from);
-asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
-
-void
-mips2_cpu_init(void)
-{
- extern void mips2_cache_init(void);
- extern void mips2_pgd_init(unsigned long page);
- extern void mips2_clear_page(unsigned long page);
- extern void mips2_copy_page(unsigned long to, unsigned long from);
- extern asmlinkage void mips2_restore_fp_context(struct sigcontext *sc);
- extern asmlinkage void mips2_save_fp_context(struct sigcontext *sc);
-
- mips_cache_init = mips2_cache_init;
- pgd_init = mips2_pgd_init;
- switch_to_user_mode = mips2_switch_to_user_mode;
- thread_saved_pc = mips2_thread_saved_pc;
- get_wchan = mips2_get_wchan;
- clear_page = mips2_clear_page;
- copy_page = mips2_copy_page;
- restore_fp_context = mips2_restore_fp_context;
- save_fp_context = mips2_save_fp_context;
-}
diff --git a/arch/mips/mips2/fp-context.S b/arch/mips/mips2/fp-context.S
deleted file mode 100644
index fc11a7fed..000000000
--- a/arch/mips/mips2/fp-context.S
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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
- */
-#include <asm/asm.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sigcontext.h>
-
-#define SDC1(r,m) \
-7: sdc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define SW(r,m) \
-7: sw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LDC1(r,m) \
-7: ldc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LW(r,m) \
-7: lw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
- .set noreorder
-/*
- * Save floating point context
- */
-LEAF(mips2_save_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
- bgez t0,1f
- nop # delay slot
- 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)) # delay slot
- .set macro
-
-1: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips2_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(mips2_restore_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
- bgez t0,1f
- LW t0,SC_FPC_CSR(a0) # delay slot
- /*
- * 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 # delay slot
- .set macro
-
-1: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips2_restore_fp_context)
diff --git a/arch/mips/mips2/pagetables.c b/arch/mips/mips2/pagetables.c
deleted file mode 100644
index 2c0061d39..000000000
--- a/arch/mips/mips2/pagetables.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 32 bit MIPS specific 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) 1996 Ralf Baechle
- */
-#include <linux/mm.h>
-#include <asm/cache.h>
-#include <asm/mipsconfig.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-void (*pgd_init)(unsigned long page);
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-void mips2_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 - PAGE_OFFSET) |
- _PAGE_TABLE),
- "0" (page),
- "1" (PAGE_SIZE/(sizeof(pmd_t)*8)),
- "i" (Create_Dirty_Excl_D));
-#endif
- /*
- * Now force writeback to ashure values are in the RAM.
- */
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_PHYSICAL);
-}
-
-void (*clear_page)(unsigned long page);
-
-/*
- * To do: cache magic, maybe FPU for 64 accesses when clearing cache pages.
- */
-void mips2_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");
-}
-
-void (*copy_page)(unsigned long to, unsigned long from);
-
-void mips2_copy_page(unsigned long to, unsigned long from)
-{
- memcpy((void *) to,
- (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
-}
diff --git a/arch/mips/mips2/showregs.c b/arch/mips/mips2/showregs.c
deleted file mode 100644
index d207d231b..000000000
--- a/arch/mips/mips2/showregs.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * linux/arch/mips/mips1/showregs.c
- *
- * Copyright (C) 1995, 1996 Ralf Baechle, Paul M. Antoine.
- */
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-void show_regs(struct pt_regs * regs)
-{
- /*
- * Saved main processor registers
- */
- printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- 0, regs->regs[1], regs->regs[2], regs->regs[3],
- regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11],
- regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19],
- regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->regs[24], regs->regs[25], regs->regs[28], regs->regs[29],
- regs->regs[30], regs->regs[31]);
-
- /*
- * Saved cp0 registers
- */
- printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
- regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
-}
diff --git a/arch/mips/mips3/Makefile b/arch/mips/mips3/Makefile
deleted file mode 100644
index e0f6bcf29..000000000
--- a/arch/mips/mips3/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Makefile for the MIPS III specific parts of the Linux/MIPS kernel.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-.S.s:
- $(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
- $(CC) $(CFLAGS) -c $< -o $*.o
-
-all: mips.o
-EXTRA_ASFLAGS = -mips3 -mcpu=r4400
-O_TARGET := mips.o
-O_OBJS := cache.o cpu.o fp-context.o memcpy.o memset.o r4xx0.o pagetables.o \
- showregs.o
-
-copy_user.o: copy_user.S
-r4xx0.o: r4xx0.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips3/cache.c b/arch/mips/mips3/cache.c
deleted file mode 100644
index 3fac95b75..000000000
--- a/arch/mips/mips3/cache.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Cache maintenance for R4000/R4400/R4600 CPUs.
- *
- * 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 by Ralf Baechle
- * FIXME: Support for SC/MC version is missing.
- */
-#include <linux/kernel.h>
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/system.h>
-
-#define STR(x) __STR(x)
-#define __STR(x) #x
-
-unsigned long page_colour_mask;
-
-/*
- * Size of the caches
- * Line size of the caches
- */
-unsigned int dcache_size, icache_size;
-unsigned int dcache_line_size, icache_line_size;
-unsigned long dcache_line_mask, icache_line_mask;
-
-/*
- * Profiling counter
- */
-extern unsigned int dflushes;
-extern unsigned int iflushes;
-
-/*
- * Pointers to code for particular CPU sub family.
- */
-static void (*wb_inv_d_cache)(void);
-static void (*inv_i_cache)(void);
-
-#define CACHELINES 512 /* number of cachelines (kludgy) */
-
-extern inline void cache(unsigned int cacheop, unsigned long addr,
- unsigned long offset, void *fault)
-{
- __asm__ __volatile__ (
- "1:\tcache\t%0,%2+%1\n\t"
- ".section\t__ex_table,\"a\"\n\t"
- STR(PTR)"\t1b,%3\n\t"
- ".text"
- : /* no outputs */
- :"ri" (cacheop),
- "o" (*(unsigned char *)addr),
- "ri" (offset),
- "ri" (fault));
-}
-
-/*
- * Code for R4000 style primary caches.
- *
- * R4000 style caches are direct-mapped, virtual indexed and physical tagged.
- * The size of cache line is either 16 or 32 bytes.
- * SC/MC versions of the CPUs add support for an second level cache with
- * upto 4mb configured as either joint or split I/D. These level two
- * caches with direct support from CPU aren't yet supported.
- */
-
-static void r4000_wb_inv_d_cache(void)
-{
- unsigned long addr = KSEG0;
- int i;
-
- for (i=CACHELINES;i;i--) {
- cache(Index_Writeback_Inv_D, addr, 0, &&fault);
- addr += 32;
- }
- if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_DB)
- return;
- for (i=CACHELINES;i;i--) {
- cache(Index_Writeback_Inv_D, addr, 16, &&fault);
- addr += 32;
- }
-fault:
-}
-
-static void r4000_inv_i_cache(void)
-{
- unsigned long addr = KSEG0;
- int i;
-
- for (i=CACHELINES;i;i--) {
- cache(Index_Invalidate_I, addr, 0, &&fault);
- addr += 32;
- }
- if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_IB)
- return;
- for (i=CACHELINES;i;i--) {
- cache(Index_Invalidate_I, addr, 16, &&fault);
- addr += 32;
- }
-fault:
-}
-
-/*
- * Code for R4600 style primary caches.
- *
- * R4600 has two way primary caches with 32 bytes line size. The way to
- * flush is selected by bith 12 of the physical address given as argument
- * to an Index_* cache operation. CPU supported second level caches are
- * not available.
- *
- * R4600 v1.0 bug: Flush way 2, then way 1 of the instruction cache when
- * using Index_Invalidate_I. IDT says this should work but is untested.
- * If this should not work, we have to disable interrupts for the broken
- * chips. The CPU might otherwise execute code from the wrong cache way
- * during an interrupt.
- */
-static void r4600_wb_inv_d_cache(void)
-{
- unsigned long addr = KSEG0;
- int i;
-
- for (i=CACHELINES;i;i-=2) {
- cache(Index_Writeback_Inv_D, addr, 8192, &&fault);
- cache(Index_Writeback_Inv_D, addr, 0, &&fault);
- addr += 32;
- }
-fault:
-}
-
-static void r4600_inv_i_cache(void)
-{
- unsigned long addr = KSEG0;
- int i;
-
- for (i=CACHELINES;i;i-=2) {
- cache(Index_Invalidate_I, addr, 8192, &&fault);
- cache(Index_Invalidate_I, addr, 0, &&fault);
- addr += 32;
- }
-fault:
-}
-
-/*
- * Flush the cache of R4x00.
- *
- * 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.)
- *
- * To do: Use Hit_Invalidate where possible to be more economic.
- * Handle SC & MC versions.
- * The decission to nuke the entire cache might be based on a better
- * decission algorithem based on the real costs.
- * Handle different cache sizes.
- * Combine the R4000 and R4600 cases.
- */
-extern inline void
-flush_d_cache(unsigned long addr, unsigned long size)
-{
- unsigned long end;
- unsigned long a;
-
- dflushes++;
- if (1 || size >= dcache_size) {
- wb_inv_d_cache();
- return;
- }
-
- /*
- * Workaround for R4600 bug. Explanation see above.
- */
- *(volatile unsigned long *)KSEG1;
-
- /*
- * Ok, we only have to invalidate parts of the cache.
- */
- a = addr & dcache_line_mask;
- end = (addr + size) & dcache_line_mask;
- while (1) {
- cache(Hit_Writeback_Inv_D, a, 0, &&fault);
- if (a == end) break;
- a += dcache_line_size;
- }
-fault:
- return;
-}
-
-extern inline void
-flush_i_cache(unsigned long addr, unsigned long size)
-{
- unsigned long end;
- unsigned long a;
-
- iflushes++;
- if (1 || size >= icache_size) {
- inv_i_cache();
- return;
- }
-
- /*
- * Ok, we only have to invalidate parts of the cache.
- */
- a = addr & icache_line_mask;
- end = (addr + size) & dcache_line_mask;
- while (1) {
- cache(Hit_Invalidate_I, a, 0, &&fault);
- if (a == end) break;
- a += icache_line_size;
- }
-fault:
- return;
-}
-
-asmlinkage void
-mips3_cacheflush(unsigned long addr, unsigned long size, unsigned int flags)
-{
- if (!(flags & CF_ALL))
- printk("mips3_cacheflush called without cachetype parameter\n");
- if (!(flags & CF_VIRTUAL))
- return; /* Nothing to do */
- if (flags & CF_DCACHE)
- flush_d_cache(addr, size);
- if (flags & CF_ICACHE)
- flush_i_cache(addr, size);
-}
-
-/* Going away. */
-asmlinkage void fd_cacheflush(unsigned long addr, unsigned long size)
-{
- cacheflush(addr, size, CF_DCACHE|CF_VIRTUAL);
-}
-
-void mips3_cache_init(void)
-{
- extern asmlinkage void handle_vcei(void);
- extern asmlinkage void handle_vced(void);
- unsigned int c0_config = read_32bit_cp0_register(CP0_CONFIG);
-
- switch (mips_cputype) {
- case CPU_R4000MC: case CPU_R4400MC:
- case CPU_R4000SC: case CPU_R4400SC:
- /*
- * Handlers not implemented yet.
- */
- set_except_vector(14, handle_vcei);
- set_except_vector(31, handle_vced);
- break;
- default:
- }
-
- /*
- * Which CPU are we running on? There are different styles
- * of primary caches in the MIPS R4xx0 CPUs.
- */
- switch (mips_cputype) {
- case CPU_R4000MC: case CPU_R4400MC:
- case CPU_R4000SC: case CPU_R4400SC:
- case CPU_R4000PC: case CPU_R4400PC:
- inv_i_cache = r4000_inv_i_cache;
- wb_inv_d_cache = r4000_wb_inv_d_cache;
- break;
- case CPU_R4600: case CPU_R4700:
- inv_i_cache = r4600_inv_i_cache;
- wb_inv_d_cache = r4600_wb_inv_d_cache;
- break;
- default:
- panic("Don't know about cache type ...");
- }
- cacheflush = mips3_cacheflush;
-
- /*
- * Find the size of primary instruction and data caches.
- * For most CPUs these sizes are the same.
- */
- dcache_size = 1 << (12 + ((c0_config >> 6) & 7));
- icache_size = 1 << (12 + ((c0_config >> 9) & 7));
- page_colour_mask = (dcache_size - 1) & ~(PAGE_SIZE - 1);
-
- /*
- * Cache line sizes
- */
- dcache_line_size = (c0_config & CONFIG_DB) ? 32 : 16;
- dcache_line_mask = ~(dcache_line_size - 1);
- icache_line_size = (c0_config & CONFIG_IB) ? 32 : 16;
- icache_line_mask = ~(icache_line_size - 1);
-
- printk("Primary D-cache size %dkb bytes, %d byte lines.\n",
- dcache_size >> 10, dcache_line_size);
- printk("Primary I-cache size %dkb bytes, %d byte lines.\n",
- icache_size >> 10, icache_line_size);
-
- /*
- * Second level cache.
- * FIXME ...
- */
- if (!(c0_config & CONFIG_SC)) {
- printk("S-cache detected. This type of of cache is not "
- "supported yet.\n");
- }
-}
diff --git a/arch/mips/mips3/cpu.c b/arch/mips/mips3/cpu.c
deleted file mode 100644
index cd8a293e5..000000000
--- a/arch/mips/mips3/cpu.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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
- */
-#include <linux/sched.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-
-extern asmlinkage void mips3_cacheflush(unsigned long addr, unsigned long nbytes, unsigned int flags);
-
-void (*mips_cache_init)(void);
-void (*switch_to_user_mode)(struct pt_regs *regs);
-
-static void
-mips3_switch_to_user_mode(struct pt_regs *regs)
-{
- regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
-}
-
-unsigned long (*thread_saved_pc)(struct thread_struct *t);
-
-/*
- * Return saved PC of a blocked thread.
- */
-static unsigned long mips3_thread_saved_pc(struct thread_struct *t)
-{
- return ((unsigned long long *)(unsigned long)t->reg29)[11];
-}
-
-unsigned long (*get_wchan)(struct task_struct *p);
-
-static unsigned long mips3_get_wchan(struct task_struct *p)
-{
- /*
- * This one depends on the frame size of schedule(). Do a
- * "disass schedule" in gdb to find the frame size. Also, the
- * code assumes that sleep_on() follows immediately after
- * interruptible_sleep_on() and that add_timer() follows
- * immediately after interruptible_sleep(). Ugly, isn't it?
- * Maybe adding a wchan field to task_struct would be better,
- * after all...
- */
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long long *)(long)p->tss.reg30)[10];
- return (unsigned long)((unsigned long long *)schedule_frame)[9];
- }
- return pc;
-}
-
-void (*pgd_init)(unsigned long page);
-void (*copy_page)(unsigned long to, unsigned long from);
-asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
-
-void
-mips3_cpu_init(void)
-{
- extern void mips3_cache_init(void);
- extern void mips3_pgd_init_32byte_lines(unsigned long page);
- extern void mips3_pgd_init_16byte_lines(unsigned long page);
- extern void mips3_clear_page_32byte_lines(unsigned long page);
- extern void mips3_clear_page_16byte_lines(unsigned long page);
- extern void mips3_copy_page_32byte_lines(unsigned long to, unsigned long from);
- extern void mips3_copy_page_16byte_lines(unsigned long to, unsigned long from);
- extern void mips3_copy_page(unsigned long to, unsigned long from);
- extern asmlinkage void mips3_restore_fp_context(struct sigcontext *sc);
- extern asmlinkage void mips3_save_fp_context(struct sigcontext *sc);
-
- mips_cache_init = mips3_cache_init;
- if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_DB) {
- pgd_init = mips3_pgd_init_32byte_lines;
- clear_page = mips3_clear_page_32byte_lines;
- copy_page = mips3_copy_page_32byte_lines;
- } else {
- pgd_init = mips3_pgd_init_16byte_lines;
- clear_page = mips3_clear_page_16byte_lines;
- copy_page = mips3_copy_page_16byte_lines;
- }
- switch_to_user_mode = mips3_switch_to_user_mode;
- thread_saved_pc = mips3_thread_saved_pc;
- get_wchan = mips3_get_wchan;
- restore_fp_context = mips3_restore_fp_context;
- save_fp_context = mips3_save_fp_context;
-}
diff --git a/arch/mips/mips3/fp-context.S b/arch/mips/mips3/fp-context.S
deleted file mode 100644
index 5e04aa61f..000000000
--- a/arch/mips/mips3/fp-context.S
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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
- */
-#include <asm/asm.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sigcontext.h>
-
-#define SDC1(r,m) \
-7: sdc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define SW(r,m) \
-7: sw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LDC1(r,m) \
-7: ldc1 r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
-#define LW(r,m) \
-7: lw r,m; \
- .section __ex_table,"a"; \
- PTR 7b,bad_stack; \
- .text
-
- .set noreorder
-/*
- * Save floating point context
- */
-LEAF(mips3_save_fp_context)
- mfc0 t1,CP0_STATUS
- sll t2,t1,2
- bgez t2,2f
- sll t2,t1,5 # delay slot
- bgez t2,1f
- cfc1 t1,fcr31 # delay slot
- /*
- * Store the 16 odd double precision registers
- */
- SDC1 ($f1,(SC_FPREGS+8)(a0))
- SDC1 ($f3,(SC_FPREGS+24)(a0))
- SDC1 ($f5,(SC_FPREGS+40)(a0))
- SDC1 ($f7,(SC_FPREGS+56)(a0))
- SDC1 ($f9,(SC_FPREGS+72)(a0))
- SDC1 ($f11,(SC_FPREGS+88)(a0))
- SDC1 ($f13,(SC_FPREGS+104)(a0))
- SDC1 ($f15,(SC_FPREGS+120)(a0))
- SDC1 ($f17,(SC_FPREGS+136)(a0))
- SDC1 ($f19,(SC_FPREGS+152)(a0))
- SDC1 ($f21,(SC_FPREGS+168)(a0))
- SDC1 ($f23,(SC_FPREGS+184)(a0))
- SDC1 ($f25,(SC_FPREGS+200)(a0))
- SDC1 ($f27,(SC_FPREGS+216)(a0))
- SDC1 ($f29,(SC_FPREGS+232)(a0))
- SDC1 ($f31,(SC_FPREGS+248)(a0))
-
- /*
- * Store the 16 even double precision registers
- */
-1: 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 t1,SC_FPC_CSR(a0)
- cfc1 t0,$0 # implementation/version
- jr ra
- .set nomacro
- SW t1,SC_FPC_EIR(a0) # delay slot
- .set macro
-
-2: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips3_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(mips3_restore_fp_context)
- mfc0 t1,CP0_STATUS
- sll t0,t1,2
- bgez t0,2f
- sll t0,t1,5 # delay slot
- bgez t0,1f
- LW t0,SC_FPC_CSR(a0) # delay slot
- /*
- * Restore the 16 odd double precision registers only
- * when enabled in the cp0 status register.
- */
- LDC1 ($f1,(SC_FPREGS+8)(a0))
- LDC1 ($f3,(SC_FPREGS+24)(a0))
- LDC1 ($f5,(SC_FPREGS+40)(a0))
- LDC1 ($f7,(SC_FPREGS+56)(a0))
- LDC1 ($f9,(SC_FPREGS+72)(a0))
- LDC1 ($f11,(SC_FPREGS+88)(a0))
- LDC1 ($f13,(SC_FPREGS+104)(a0))
- LDC1 ($f15,(SC_FPREGS+120)(a0))
- LDC1 ($f17,(SC_FPREGS+136)(a0))
- LDC1 ($f19,(SC_FPREGS+152)(a0))
- LDC1 ($f21,(SC_FPREGS+168)(a0))
- LDC1 ($f23,(SC_FPREGS+184)(a0))
- LDC1 ($f25,(SC_FPREGS+200)(a0))
- LDC1 ($f27,(SC_FPREGS+216)(a0))
- LDC1 ($f29,(SC_FPREGS+232)(a0))
- LDC1 ($f31,(SC_FPREGS+248)(a0))
-
- /*
- * Restore the 16 even double precision registers
- * when cp1 was enabled in the cp0 status register.
- */
-1: 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 # delay slot
- .set macro
-
-2: jr ra
- .set nomacro
- nop # delay slot
- .set macro
- END(mips3_restore_fp_context)
- .set reorder
diff --git a/arch/mips/mips3/memcpy.S b/arch/mips/mips3/memcpy.S
deleted file mode 100644
index 6f03032a6..000000000
--- a/arch/mips/mips3/memcpy.S
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * arch/mips/mips3/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 64 bit MIPS CPUs.
- * Much faster than the old memcpy but definately work in progress.
- * The list of tricks for a good memcpy is long ...
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-
-#define BLOCK_SIZE (SZREG*4)
-
-#define SWAP(x,y) \
- subu x,x,y; \
- addu y,x,y; \
- subu x,y,x
-
-#define EX(addr,handler) \
- .section __ex_table,"a"; \
- PTR addr, handler; \
- .text
-#define UEX(addr,handler) \
- EX(addr,handler); \
- EX(addr+4,handler)
-
- .set noreorder
- .set noat
-
-/* ---------------------------------------------------------------------- */
-
-not_dw_aligned:
-/*
- * At least one address is missaligned.
- * Let's see if we can fix the alignment.
- */
- LONG_SUBU v1,zero,a0
- andi v1,SZREG-1
- sltu t0,v0,v1
- MOVN(v1,v0,t0)
- beqz v1,still_not_aligned
- 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, now the destination address is 8-byte aligned.
- * Is the source also aligned?
- */
- andi t0,a1,SZREG-1
- beqz t0,align8 # fine ...
-
-/*
- * Bad. We could only fix the alignment of the destination address.
- * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned
- * load and aligned stores.
- */
-still_not_aligned:
- ori v1,v0,BLOCK_SIZE-1 # delay slot
- xori v1,BLOCK_SIZE-1
- beqz v1,copy_left_over
- nop # delay slot
- LONG_SUBU v0,v1
- LONG_ADDU v1,a0
-
-1: uld t0,(a1)
- UEX(1b, fault)
-2: uld t1,8(a1)
- UEX(2b, fault)
-2: uld t2,16(a1)
- UEX(2b, fault)
-2: uld t3,24(a1)
- UEX(2b, fault)
-2: sd t0,(a0)
- EX(2b, fault)
-2: sd t1,8(a0)
- EX(2b, fault_plus_one_reg)
-2: sd t2,16(a0)
- EX(2b, fault_plus_two_reg)
-2: sd t3,24(a0)
- EX(2b, fault_plus_three_reg)
- 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
-
-/* ---------------------------------------------------------------------- */
-
-LEAF(__copy_user)
-
- or t1,a0,a1
- andi t1,SZREG-1
- bnez t1,not_dw_aligned
- move v0,a2 # delay slot
-
-align8:
- 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: ld t0,(a1)
- EX(1b, fault)
-2: ld t1,8(a1)
- EX(2b, fault)
-2: ld t2,16(a1)
- EX(2b, fault)
-2: ld t3,24(a1)
- EX(2b, fault)
-2: sd t0,(a0)
- EX(2b, fault)
-2: sd t1,8(a0)
- EX(2b, fault_plus_one_reg)
-2: sd t2,16(a0)
- EX(2b, fault_plus_two_reg)
-2: sd t3,24(a0)
- EX(2b, fault_plus_three_reg)
- LONG_ADDIU a0,BLOCK_SIZE
- bne a0,v1,1b
- LONG_ADDIU a1,BLOCK_SIZE # delay slot
-9:
-
-/*
- * We've got upto 31 bytes left to copy ...
- */
-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_one_reg: LONG_ADDIU v0,SZREG
- jr ra
-fault_plus_two_reg: LONG_ADDIU v0,SZREG*2
- jr ra
-fault_plus_three_reg: LONG_ADDIU v0,SZREG*3
- jr ra
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * For now we use __copy_user for __memcpy, too. This is efficient (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/mips3/memset.c b/arch/mips/mips3/memset.c
deleted file mode 100644
index e92a0907f..000000000
--- a/arch/mips/mips3/memset.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 memset for 64 bit MIPS CPUs.
- */
-#include <linux/linkage.h>
-#include <linux/string.h>
-
-static void __inline__ b_memset(void *s, unsigned long long c, size_t count)
-{
- unsigned char *p = s;
-
- while(count--)
- *(p++) = c;
-}
-
-static void __inline__ dw_memset(void *s, unsigned long long c, size_t count)
-{
- unsigned long long *p = s;
-
- count >>= 3;
- while(count--)
- *(p++) = c;
-}
-
-asm( ".globl\t__generic_memset_b\n\t"
- ".align\t2\n\t"
- ".type\t__generic_memset_b,@function\n\t"
- ".ent\t__generic_memset_b,0\n\t"
- ".frame\t$29,0,$31\n"
- "__generic_memset_b:\n\t"
- "andi\t$5,0xff\n\t"
- "dsll\t$2,$5,8\n\t"
- "or\t$5,$2\n\t"
- "dsll\t$2,$5,16\n\t"
- "or\t$5,$2\n\t"
- "dsll32\t$2,$5,0\n\t"
- "or\t$5,$2\n\t"
- ".end\t__generic_memset_b\n\t"
- ".size\t__generic_memset_b,.-t__generic_memset_b");
-
-/*
- * Fill small area bytewise. For big areas fill the source bytewise
- * until the pointer is doubleword aligned, then fill in doublewords.
- * Fill the rest again in single bytes.
- */
-void __generic_memset_dw(void *s, unsigned long long c, size_t count)
-{
- unsigned long i;
-
- /*
- * Fill small areas bytewise.
- */
- if (count <= 16) {
- b_memset(s, c, count);
- return;
- }
-
- /*
- * Pad for 8 byte boundary
- */
- i = 8 - ((unsigned long)s & 7);
- b_memset(s, c, i);
- s += i;
- count -= i;
-
- /*
- * Now start filling with aligned doublewords
- */
- dw_memset(s, c, count);
- s += (count | 7) ^ 7;
- count &= 7;
-
- /*
- * And do what ever is left over again with single bytes.
- */
- b_memset(s, c, count);
-}
diff --git a/arch/mips/mips3/pagetables.c b/arch/mips/mips3/pagetables.c
deleted file mode 100644
index e8cb83d03..000000000
--- a/arch/mips/mips3/pagetables.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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
- *
- * Functions that manipulate entire pages.
- *
- * Not nice to have all these functions in two versions for cpus with
- * different cache line size but it seems to be by far the fastest thing
- * to schedule the cache instructions immediately before the store
- * instructions. For example using the clear_page() version for 16 byte
- * lines on machine with 32 byte lines gives a measured penalty of
- * ~1280 cycles per page.
- */
-#include <linux/mm.h>
-#include <asm/cache.h>
-#include <asm/mipsconfig.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-extern unsigned int dflushes;
-
-/*
- * Initialize new page directory with pointers to invalid ptes.
- */
-void mips3_pgd_init_32byte_lines(unsigned long page)
-{
- unsigned long dummy1, dummy2;
-
- /*
- * We generate dirty lines in the datacache, overwrite them
- * then writeback the cache.
- */
- __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:\tcache\t%5,(%0)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%2,8(%0)\n\t"
- "sd\t%2,16(%0)\n\t"
- "sd\t%2,24(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "cache\t%5,-32(%0)\n\t"
- "sd\t%2,-32(%0)\n\t"
- "sd\t%2,-24(%0)\n\t"
- "sd\t%2,-16(%0)\n\t"
- "bne\t%0,%1,1b\n\t"
- "sd\t%2,-8(%0)\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 + PAGE_SIZE - 64),
- "i" (Create_Dirty_Excl_D)
- :"$1");
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- ".set\tmips3\n\t"
- "1:\tcache\t%3,(%0)\n\t"
- "bne\t%0,%1,1b\n\t"
- "daddiu\t%0,32\n\t"
- ".set\tmips0\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1)
- :"0" (page),
- "r" (page + PAGE_SIZE - 32),
- "i" (Hit_Writeback_D));
- dflushes++;
-
-#if 0
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
-#endif
-}
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-void mips3_pgd_init_16byte_lines(unsigned long page)
-{
- unsigned long dummy1, dummy2;
-
- /*
- * We generate dirty lines in the datacache, overwrite them
- * then writeback the cache.
- */
- __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:\tcache\t%5,(%0)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%2,8(%0)\n\t"
- "cache\t%5,16(%0)\n\t"
- "sd\t%2,16(%0)\n\t"
- "sd\t%2,24(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "cache\t%5,-32(%0)\n\t"
- "sd\t%2,-32(%0)\n\t"
- "sd\t%2,-24(%0)\n\t"
- "cache\t%5,-16(%0)\n\t"
- "sd\t%2,-16(%0)\n\t"
- "bne\t%0,%1,1b\n\t"
- "sd\t%2,-8(%0)\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 + PAGE_SIZE - 64),
- "i" (Create_Dirty_Excl_D)
- :"$1");
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- ".set\tmips3\n\t"
- "1:\tcache\t%3,(%0)\n\t"
- "bne\t%0,%1,1b\n\t"
- "daddiu\t%0,16\n\t"
- ".set\tmips0\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1)
- :"0" (page),
- "r" (page + PAGE_SIZE - 16),
- "i" (Hit_Writeback_D));
- dflushes++;
-
-#if 0
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
-#endif
-}
-
-/*
- * Zero an entire page.
- */
-
-void (*clear_page)(unsigned long page);
-
-void mips3_clear_page_32byte_lines(unsigned long page)
-{
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\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\tat\n\t"
- ".set\treorder"
- :"=r" (page)
- :"0" (page),
- "I" (PAGE_SIZE),
- "i" (Create_Dirty_Excl_D)
- :"$1","memory");
-}
-
-void mips3_clear_page_16byte_lines(unsigned long page)
-{
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\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\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.
- */
-void (*copy_page)(unsigned long to, unsigned long from);
-
-void mips3_copy_page_32byte_lines(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"
- "daddiu\t$1,%0,%8\n"
- "1:\tcache\t%9,(%0)\n\t"
- "ld\t%2,(%1)\n\t"
- "ld\t%3,8(%1)\n\t"
- "ld\t%4,16(%1)\n\t"
- "ld\t%5,24(%1)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%3,8(%0)\n\t"
- "sd\t%4,16(%0)\n\t"
- "sd\t%5,24(%0)\n\t"
- "cache\t%9,32(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "daddiu\t%1,64\n\t"
- "ld\t%2,-32(%1)\n\t"
- "ld\t%3,-24(%1)\n\t"
- "ld\t%4,-16(%1)\n\t"
- "ld\t%5,-8(%1)\n\t"
- "sd\t%2,-32(%0)\n\t"
- "sd\t%3,-24(%0)\n\t"
- "sd\t%4,-16(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- "sd\t%5,-8(%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),
- "i" (Create_Dirty_Excl_D));
-}
-
-void mips3_copy_page_16byte_lines(unsigned long to, unsigned long from)
-{
- unsigned dummy1, dummy2;
- unsigned long reg1, reg2;
-
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "daddiu\t$1,%0,%6\n"
- "1:\tcache\t%7,(%0)\n\t"
- "ld\t%2,(%1)\n\t"
- "ld\t%3,8(%1)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%3,8(%0)\n\t"
- "cache\t%7,16(%0)\n\t"
- "ld\t%2,16(%1)\n\t"
- "ld\t%3,24(%1)\n\t"
- "sd\t%2,16(%0)\n\t"
- "sd\t%3,24(%0)\n\t"
- "cache\t%7,32(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "daddiu\t%1,64\n\t"
- "ld\t%2,-32(%1)\n\t"
- "ld\t%3,-24(%1)\n\t"
- "sd\t%2,-32(%0)\n\t"
- "sd\t%3,-24(%0)\n\t"
- "cache\t%7,-16(%0)\n\t"
- "ld\t%2,-16(%1)\n\t"
- "ld\t%3,-8(%1)\n\t"
- "sd\t%2,-16(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- "sd\t%3,-8(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1), "=r" (dummy2),
- "=&r" (reg1), "=&r" (reg2)
- :"0" (to), "1" (from),
- "I" (PAGE_SIZE),
- "i" (Create_Dirty_Excl_D));
-}
diff --git a/arch/mips/mips3/r4xx0.S b/arch/mips/mips3/r4xx0.S
deleted file mode 100644
index a282998ac..000000000
--- a/arch/mips/mips3/r4xx0.S
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * arch/mips/mips3/r4xx0.S
- *
- * Copyright (C) 1994, 1995, 1996 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!
- *
- * CAVEATS: The R4000/R4400/R4600 manual say that the operation of a memory
- * reference associated with a instruction immediately after a tlpb
- * instruction is undefined. It seems that the R4600 v2.0 also
- * failes to handle the case where a tlbp instruction follows a
- * (mapped???) memory reference. In this case c0_index gets
- * overwritten by some value which I suppose to be the entry
- * mapping the associated instruction's memory reference.
- *
- * This needs a complete overhaul; it was written for a Linux kernel that
- * handled it's page tables the old i386 way ...
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * Use this to activate extra TLB error checking
- */
-#define CONF_DEBUG_TLB
-
-/*
- * Use this to activate extra TLB profiling code
- * (not implemented yet)
- */
-#undef CONF_PROFILE_TLB
-
-#ifdef __SMP__
-#error "Fix this for SMP"
-#else
-#define current current_set
-#endif
-
-MODE_ALIAS = 0x0016 # uncachable
-
- .text
- .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
- nop
- tlbp
- nop
- 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 : %016Lx\n")
- dmfc0 a1,CP0_EPC
- PRINT("c0_epc : %016Lx\n")
- jal show_regs
- move a0,sp
- jal dump_tlb_nonwired
- 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
-// mfc0 k1,CP0_CONTEXT
- dsra k1,1
- lwu k0,(k1) # Never causes nested exception
- lwu k1,4(k1)
- dsrl k0,6 # Convert to EntryLo format
- dsrl k1,6 # Convert to EntryLo format
- dmtc0 k0,CP0_ENTRYLO0
- dmtc0 k1,CP0_ENTRYLO1
- nop # for R4[04]00 pipeline
- tlbwr
- nop # for R4[04]00 pipeline
- nop
- nop
- /*
- * We don't know whether the original access was read or
- * write, so return and see what happens...
- */
- eret
-
- /*
- * Handle invalid exception
- *
- * There are two possible causes for an invalid (tlbl)
- * exception:
- * 1) pages with present bit set but the valid bit clear
- * 2) nonexistant pages
- * Case one needs fast handling, therefore don't save
- * registers yet.
- *
- * k0 contains c0_index.
- */
-invalid_tlbl:
-#ifdef CONFIG_TLB_SHUTDOWN
- /*
- * Remove entry so we don't need to care later
- * For sake of the R4000 V2.2 pipeline the tlbwi insn
- * has been moved down. Moving it around is juggling with
- * explosives...
- */
- lui k1,0x0008
- or k0,k1
- dsll k0,13
- dmtc0 k0,CP0_ENTRYHI
- dmtc0 zero,CP0_ENTRYLO0
- dmtc0 zero,CP0_ENTRYLO1
-#endif
- /*
- * Test present bit in entry
- */
- dmfc0 k0,CP0_BADVADDR
- srl k0,12
- sll k0,2
-#ifdef CONFIG_TLB_SHUTDOWN
- tlbwi # do not move!
-#endif
- lui k1,%HI(TLBMAP)
- addu k0,k1
- lw k1,(k0)
- andi k1,(_PAGE_PRESENT|_PAGE_READ)
- xori k1,(_PAGE_PRESENT|_PAGE_READ)
- bnez k1,nopage_tlbl
- /*
- * Present and read bits are set -> set valid and accessed bits
- */
- lw k1,(k0) # delay slot
- ori k1,(_PAGE_VALID|_PAGE_ACCESSED)
- sw k1,(k0)
- eret
-
- /*
- * Page doesn't exist. Lots of work which is less important
- * for speed needs to be done, so hand it all over to the
- * kernel memory management routines.
- */
-nopage_tlbl: SAVE_ALL
- dmfc0 a2,CP0_BADVADDR
- STI
- REG_S sp,FR_ORIG_REG2(sp)
- .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)
- nop
- nop
- tlbp # find faulting entry
- nop
- 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
- dmfc0 a1,CP0_BADVADDR
- PRINT("c0_badvaddr == %016Lx\n")
- mfc0 a1,CP0_INDEX
- PRINT("c0_index == %08x\n")
- dmfc0 a1,CP0_ENTRYHI
- PRINT("c0_entryhi == %016Lx\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 /* CONFIG_TLB_SHUTDOWN */
- .set noat
- SAVE_ALL
- dmfc0 a2,CP0_BADVADDR
- STI
- REG_S sp,FR_ORIG_REG2(sp)
- .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)
- nop
- nop
- tlbp # find faulting entry
- nop
- 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
-
-/*
- * Flush the complete TLB
- */
- .set noreorder
- LEAF(tlbflush)
- li t0,PM_4K
- mtc0 t0,CP0_PAGEMASK
- lw t0,mips_tlb_entries /* mips_tlb_enbtries is set */
- /* by bi_EarlySnarf() */
- 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
- nop # delay slot
- END(tlbflush)
-
-/*
- * Flush a single entry from the TLB
- *
- * Parameters: a0 - unsigned long address
- */
- .set noreorder
- LEAF(tlbflush_page)
- /*
- * Step 1: Wipe out old TLB information. Not shure if
- * we really need that step; call it paranoia ...
- * In order to do that we need to disable interrupts.
- */
- li t3,TLBMAP # then wait 3 cycles
- ori t1,a0,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,a0,12 # wait again three cycles
- sll t4,t4,PTRLOG
- dmtc0 zero,CP0_ENTRYLO0
- nop
- tlbp # now query the TLB
- nop
- 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 an entry for the pgd ...
- */
-1: mtc0 t3,CP0_ENTRYHI
- nop # wait 3 cycles
- nop
- nop
- nop
- tlbp # TLB lookup
- nop
- nop
- nop
- mfc0 t1,CP0_INDEX # wait 3 cycles
- bltz t1,1f # No old entry?
- nop
- tlbwi # gotcha ...
-1: jr ra
- nop # delay slot
- END(tlbflush_page)
-
-/*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- * FIXME: We don't need to disable interrupts anymore.
- * FIXME: Do some cache magic for faster loading/saving.
- */
- .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
- */
- sd s0,TOFF_REG16(t0)
- sd s1,TOFF_REG17(t0)
- sd s2,TOFF_REG18(t0)
- sd s3,TOFF_REG19(t0)
- sd s4,TOFF_REG20(t0)
- sd s5,TOFF_REG21(t0)
- sd s6,TOFF_REG22(t0)
- sd s7,TOFF_REG23(t0)
- sd gp,TOFF_REG28(t0)
- sd sp,TOFF_REG29(t0)
- sd fp,TOFF_REG30(t0)
-
- /*
- * Save floating point state
- */
- sll t2,t1,2
- bgez t2,2f
- sd 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: ld s0,TOFF_REG16(a0)
- ld s1,TOFF_REG17(a0)
- ld s2,TOFF_REG18(a0)
- ld s3,TOFF_REG19(a0)
- ld s4,TOFF_REG20(a0)
- ld s5,TOFF_REG21(a0)
- ld s6,TOFF_REG22(a0)
- ld s7,TOFF_REG23(a0)
- ld gp,TOFF_REG28(a0)
- ld sp,TOFF_REG29(a0)
- ld fp,TOFF_REG30(a0)
- ld 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
- jr ra
- tlbwi # delay slot
- END(load_pgd)
-
-/*
- * 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.
- *
- * FIXME: This function will fail for syscalls with more than four
- * arguments from kernelspace.
- *
- * a0 (struct pt_regs *) pointer to user registers
- * a1 (syscall_t) pointer to syscall to do
- * a2 (int) number of arguments to syscall
- */
-#if defined (__MIPSEB__) && defined (__mips64)
-#define bo 4
-#else
-#define bo 0
-#endif
- .set reorder
- .text
-NESTED(do_syscalls, 64, sp)
- LONG_SUBU sp,64
- REG_S ra,56(sp)
- dsll a2,a2,PTRLOG
- lw t1,dst(a2)
- move t2,a1
- REG_L t0,FR_REG29(a0) # get old user stack pointer
- jalr t1
-
-7: lw t1,24+bo(t0) # parameter #7 from usp
- REG_S t1,SZREG*6(sp)
-6: lw t1,20+bo(t0) # parameter #6 from usp
- REG_S t1,SZREG*5(sp)
-5: lw t1,16+bo(t0) # parameter #5 from usp
- REG_S t1,SZREG*4(sp)
-
-4: lw a3,FR_REG7+bo(a0) # 4 args
-3: lw a2,FR_REG6+bo(a0) # 3 args
-2: lw a1,FR_REG5+bo(a0) # 2 args
-1: lw a0,FR_REG4+bo(a0) # 1 args
- jalr t2
- ld ra,56(sp)
- addiu sp,64
- jr ra
-0: jalr t2 # 0 args, just pass a0
- ld ra,56(sp)
- LONG_ADDIU sp,64
- jr ra
- END(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
- .text
-
-#ifdef CONFIG_REVERSE
-
-/*
- * Same as above but for processes running with reverse byte order.
- * When exec(2)ing a file the system detects normal/reverse byteorder in
- * an executable and
- * - sets the appropriate vector for syscalls and other low level
- * routines that depend of userspace byteorder.
- * - set the reverse byteorder flag in c0_status
- * - marks the process as reverse in the process table.
- */
-#define REG_SWAP(r,t) \
- .set push; \
- .set noat; \
- sll $1,r,24; \
- andi t,r,0xff00; \
- sll t,$t,8; \
- or $1,t; \
- srl t,r,8; \
- andi t,$t,0xff00; \
- or $1,t; \
- srl r,r,24; \
- or $1,r; \
- .set pop
-
- .set reorder
- .text
-NESTED(do_syscalls_rev, 64, sp)
- LONG_SUBU sp,64
- REG_S ra,56(sp)
- dsll a2,a2,PTRLOG
- lw t1,dst_rev(a2)
- move t2,a1
- REG_L t0,FR_REG29(a0) # get old user stack pointer
- jalr t1
-
-7: lw t1,24+bo(t0) # parameter #7 from usp
- REG_SWAP(t1,v0) # convert byteorder
- REG_S t1,SZREG*6(sp)
-6: lw t1,20+bo(t0) # parameter #6 from usp
- REG_SWAP(t1,v0) # convert byteorder
- REG_S t1,SZREG*5(sp)
-5: lw t1,16+bo(t0) # parameter #5 from usp
- REG_SWAP(t1,v0) # convert byteorder
- REG_S t1,SZREG*4(sp)
-
-4: lw a3,FR_REG7+bo(a0) # 4 args
-3: lw a2,FR_REG6+bo(a0) # 3 args
-2: lw a1,FR_REG5+bo(a0) # 2 args
-1: lw a0,FR_REG4+bo(a0) # 1 args
- jalr t2
- ld ra,56(sp)
- addiu sp,64
- jr ra
-0: jalr t2 # 0 args, just pass a0
- ld ra,56(sp)
- LONG_ADDIU sp,64
- jr ra
- END(do_syscalls)
-
- .rdata
- .align PTRLOG
-dst_rev: 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
- .text
-
-#endif /* CONFIG_REVERSE */
diff --git a/arch/mips/mips3/showregs.c b/arch/mips/mips3/showregs.c
deleted file mode 100644
index 651cb6a24..000000000
--- a/arch/mips/mips3/showregs.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/mips/mips3/showregs.c
- *
- * Copyright (C) 1995, 1996 Ralf Baechle
- */
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-void show_regs(struct pt_regs * regs)
-{
- /*
- * Saved main processor registers
- */
- printk("$0 : %016Lx %016Lx %016Lx %016Lx\n",
- 0ULL, regs->regs[1], regs->regs[2], regs->regs[3]);
- printk("$4 : %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
- printk("$8 : %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
- printk("$12: %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
- printk("$16: %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
- printk("$20: %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
- printk("$24: %016Lx %016Lx\n",
- regs->regs[24], regs->regs[25]);
- printk("$28: %016Lx %016Lx %016Lx %016Lx\n",
- regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
-
- /*
- * Saved cp0 registers
- */
- printk("epc : %016Lx\nStatus: %08x\nCause : %08x\n",
- regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
-}
diff --git a/arch/mips/mips4/Makefile b/arch/mips/mips4/Makefile
deleted file mode 100644
index d5827861b..000000000
--- a/arch/mips/mips4/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the MIPS IV specific parts of the Linux/MIPS kernel.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-.S.s:
- $(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
- $(CC) $(CFLAGS) -c $< -o $*.o
-
-all: mips.o
-EXTRA_ASFLAGS = -mips4 -mcpu=r8000
-O_TARGET := mips.o
-O_OBJS := cpu.o pagetables.o showregs.o
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips4/README b/arch/mips/mips4/README
deleted file mode 100644
index 22e90921b..000000000
--- a/arch/mips/mips4/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory contains the start of the R8000/R10000 specific part. I
-tried to support this CPU as good as possible without a machine and
-without detailed documentation.
diff --git a/arch/mips/mips4/cpu.c b/arch/mips/mips4/cpu.c
deleted file mode 100644
index ef5a3f8db..000000000
--- a/arch/mips/mips4/cpu.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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
- */
-#include <linux/sched.h>
-
-#include <asm/cache.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-
-extern asmlinkage void mips4_cacheflush(void *addr, int nbytes, unsigned int flags);
-
-unsigned long page_colour_mask;
-
-void (*mips_cache_init)(void);
-
-static void
-mips4_cache_init(void)
-{
- /*
- * 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;
- cacheflush = mips4_cacheflush;
- /*
- * 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!");
-}
-
-void (*switch_to_user_mode)(struct pt_regs *regs);
-
-static void
-mips4_switch_to_user_mode(struct pt_regs *regs)
-{
- regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
-}
-
-unsigned long (*thread_saved_pc)(struct thread_struct *t);
-
-/*
- * Return saved PC of a blocked thread.
- * XXX This works only for 64 bit kernels.
- */
-static unsigned long mips4_thread_saved_pc(struct thread_struct *t)
-{
- return ((unsigned long long *)(unsigned long)t->reg29)[11];
-}
-
-unsigned long (*get_wchan)(struct task_struct *p);
-
-static unsigned long mips4_get_wchan(struct task_struct *p)
-{
- /*
- * This one depends on the frame size of schedule(). Do a
- * "disass schedule" in gdb to find the frame size. Also, the
- * code assumes that sleep_on() follows immediately after
- * interruptible_sleep_on() and that add_timer() follows
- * immediately after interruptible_sleep(). Ugly, isn't it?
- * Maybe adding a wchan field to task_struct would be better,
- * after all...
- */
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long long *)(long)p->tss.reg30)[10];
- return (unsigned long)((unsigned long long *)schedule_frame)[9];
- }
- return pc;
-}
-
-extern void mips4_clear_page(unsigned long page);
-extern void mips4_copy_page(unsigned long to, unsigned long from);
-asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-asmlinkage void (*save_fp_context)(struct sigcontext *sc);
-
-void
-mips4_cpu_init(void)
-{
- extern void mips4_pgd_init(unsigned long page);
- extern asmlinkage void mips4_restore_fp_context(struct sigcontext *sc);
- extern asmlinkage void mips4_save_fp_context(struct sigcontext *sc);
-
- mips_cache_init = mips4_cache_init;
- pgd_init = mips1_pgd_init;
- switch_to_user_mode = mips4_switch_to_user_mode;
- thread_saved_pc = mips4_thread_saved_pc;
- get_wchan = mips4_get_wchan;
- clear_page = mips4_clear_page;
- restore_fp_context = mips4_restore_fp_context;
- save_fp_context = mips4_save_fp_context;
-}
diff --git a/arch/mips/mips4/pagetables.c b/arch/mips/mips4/pagetables.c
deleted file mode 100644
index b1b86290a..000000000
--- a/arch/mips/mips4/pagetables.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 64 bit MIPS specific 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) 1996 Ralf Baechle
- */
-#include <linux/mm.h>
-#include <asm/cache.h>
-#include <asm/mipsconfig.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-void (*pgd_init)(unsigned long page);
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-void mips4_pgd_init(unsigned long page)
-{
- unsigned long dummy1, dummy2;
-
- /*
- * 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.
- * FIXME: This is the same like the R4000 version. We could do some
- * R10000 trickery using caching mode "uncached accelerated".
- */
- __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:\t"
- "cache\t%5,(%0)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%2,8(%0)\n\t"
- "cache\t%5,16(%0)\n\t"
- "sd\t%2,16(%0)\n\t"
- "sd\t%2,24(%0)\n\t"
- "cache\t%5,32(%0)\n\t"
- "sd\t%2,32(%0)\n\t"
- "sd\t%2,40(%0)\n\t"
- "cache\t%5,48(%0)\n\t"
- "sd\t%2,48(%0)\n\t"
- "sd\t%2,56(%0)\n\t"
- "subu\t%1,1\n\t"
- "bnez\t%1,1b\n\t"
- "addiu\t%0,64\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)*16)),
- "i" (Create_Dirty_Excl_D)
- :"$1");
- /*
- * Now force writeback to ashure values are in the RAM.
- */
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
-}
-
-void (*clear_page)(unsigned long page);
-
-/*
- * To do: cache magic
- */
-void mips4_clear_page(unsigned long page)
-{
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "daddiu\t$1,%0,%2\n"
- "1:\tsd\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"
- "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\tat\n\t"
- ".set\treorder"
- :"=r" (page)
- :"0" (page),
- "I" (PAGE_SIZE)
- :"$1","memory");
-}
-
-void (*copy_page)(unsigned long to, unsigned long from);
-
-/*
- * This is horribly inefficient ...
- */
-void mips4_copy_page(unsigned long to, unsigned long from)
-{
- /*
- * Force writeback of old page to memory. We don't know the
- * virtual address, so we have to flush the entire cache ...
- */
- cacheflush(0, ~0, CF_DCACHE|CF_VIRTUAL);
- sync_mem();
- memcpy((void *) to,
- (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
- /*
- * Now writeback the page again if colour has changed.
- */
- if (page_colour(from) != page_colour(to))
- cacheflush(0, ~0, CF_DCACHE|CF_VIRTUAL);
-}
diff --git a/arch/mips/mm/.cvsignore b/arch/mips/mm/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/mm/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 6f69a0ee6..1205b2bf3 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -8,6 +8,7 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := extable.o init.o fault.o stack.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
index 000000000..977fa1a30
--- /dev/null
+++ b/arch/mips/mm/andes.c
@@ -0,0 +1,102 @@
+/* $Id: andes.c,v 1.3 1996/07/29 11:10:06 dm 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/segment.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/fault.c b/arch/mips/mm/fault.c
index f1462eff9..1ad0ff48e 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -1,7 +1,7 @@
/*
* arch/mips/mm/fault.c
*
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*/
#include <linux/signal.h>
#include <linux/sched.h>
@@ -14,13 +14,15 @@
#include <linux/mman.h>
#include <linux/mm.h>
-#include <asm/cache.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.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.
*/
@@ -31,9 +33,8 @@ extern void die_if_kernel(char *, struct pt_regs *, long);
* 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;
@@ -41,9 +42,8 @@ do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
unsigned long fixup;
#if 0
- printk("do_page_fault() #1: %s %08lx (epc == %08lx, ra == %08lx)\n",
- writeaccess ? "writeaccess to" : "readaccess from",
- address, regs->cp0_epc, regs->regs[31]);
+ printk("[%s:%d:%08lx:%ld:%08lx]", current->comm, current->pid,
+ address, writeaccess, regs->cp0_epc);
#endif
down(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -70,7 +70,7 @@ good_area:
handle_mm_fault(vma, address, writeaccess);
up(&mm->mmap_sem);
- return;
+ return;
/*
* Something tried to access memory that isn't in our memory map..
@@ -89,6 +89,7 @@ bad_area:
regs->cp0_epc = new_epc;
return;
}
+
if (user_mode(regs)) {
tsk->tss.cp0_badvaddr = address;
tsk->tss.error_code = writeaccess;
@@ -101,6 +102,9 @@ bad_area:
(unsigned long) regs->cp0_epc,
(unsigned long) regs->regs[31]);
#endif
+
+ current->tss.cp0_badvaddr = address;
+ current->tss.error_code = writeaccess;
force_sig(SIGSEGV, tsk);
return;
}
@@ -109,11 +113,7 @@ bad_area:
* terminate things with extreme prejudice.
*/
printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
-#ifdef __mips64
- "address %08lx, epc == %08Lx\n", address, regs->cp0_epc);
-#else
- "address %08lx, epc == %016lx\n", address, regs->cp0_epc);
-#endif
+ "address %08lx, epc == %08lx\n", address, regs->cp0_epc);
die_if_kernel("Oops", regs, writeaccess);
do_exit(SIGKILL);
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 149349102..cfcfcaf00 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -21,23 +21,32 @@
#endif
#include <asm/bootinfo.h>
-#include <asm/cache.h>
+#include <asm/cachectl.h>
#include <asm/dma.h>
#include <asm/jazzdma.h>
#include <asm/vector.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
+#include <asm/segment.h>
#include <asm/pgtable.h>
-#include <asm/page.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
extern void deskstation_tyne_dma_init(void);
extern void show_net_buffers(void);
+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
@@ -56,7 +65,6 @@ pte_t * __bad_pagetable(void)
#endif
page = (unsigned long) empty_bad_page_table;
- page = page_to_ptp(page);
/*
* 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
@@ -104,13 +112,59 @@ pte_t * __bad_pagetable(void)
return (pte_t *)page;
}
+static inline void
+__zeropage(unsigned long page)
+{
+ unsigned long dummy1, dummy2;
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+ /*
+ * Use 64bit code even for Linux/MIPS 32bit on R4000
+ */
+ __asm__ __volatile__(
+ ".set\tnoreorder\n"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n"
+ "1:\tsd\t$0,(%0)\n\t"
+ "subu\t%1,1\n\t"
+ "bnez\t%1,1b\n\t"
+ "addiu\t%0,8\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n"
+ ".set\treorder"
+ :"=r" (dummy1),
+ "=r" (dummy2)
+ :"0" (page),
+ "1" (PAGE_SIZE/8));
+#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
+ __asm__ __volatile__(
+ ".set\tnoreorder\n"
+ "1:\tsw\t$0,(%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)
+ :"0" (page),
+ "1" (PAGE_SIZE/4));
+#endif
+}
+
+static inline void
+zeropage(unsigned long page)
+{
+ flush_page_to_ram(page);
+ sync_mem();
+ __zeropage(page);
+}
+
pte_t __bad_page(void)
{
extern char empty_bad_page[PAGE_SIZE];
unsigned long page = (unsigned long)empty_bad_page;
- clear_page(page_to_ptp(page));
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
+ zeropage(page);
return pte_mkdirty(mk_pte(page, PAGE_SHARED));
}
@@ -146,8 +200,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
- mips_cache_init();
- 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);
}
@@ -156,7 +209,7 @@ 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
if (mips_machgroup == MACH_GROUP_JAZZ)
@@ -177,9 +230,10 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
clear_bit(PG_reserved, &mem_map[tmp].flags);
/*
- * For rPC44 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.
+ * 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)
@@ -187,10 +241,15 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++)
clear_bit(PG_reserved, &mem_map[tmp].flags);
+
+#ifdef CONFIG_SGI
+ prom_fixup_mem_map(start_mem, high_memory);
+#endif
+
#ifdef CONFIG_DESKSTATION_TYNE
- if (mips_machtype == MACH_DESKSTATION_TYNE)
- deskstation_tyne_dma_init();
+ deskstation_tyne_dma_init();
#endif
+
for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
/*
* This is only for PC-style DMA. The onboard DMA
@@ -200,9 +259,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
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)
+ 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;
}
diff --git a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c
new file mode 100644
index 000000000..9a0c33328
--- /dev/null
+++ b/arch/mips/mm/loadmmu.c
@@ -0,0 +1,105 @@
+/* $Id: loadmmu.c,v 1.6 1996/07/29 11:10:07 dm 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/segment.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
index 000000000..b43d7a2bc
--- /dev/null
+++ b/arch/mips/mm/r2300.c
@@ -0,0 +1,271 @@
+/* $Id: r2300.c,v 1.5 1996/07/29 11:10:07 dm 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/segment.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"
+ "sd\t%2,-16(%0)\n\t"
+ "sd\t%3,-12(%0)\n\t"
+ "sd\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\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
index 000000000..ea983656b
--- /dev/null
+++ b/arch/mips/mm/r4xx0.c
@@ -0,0 +1,2456 @@
+/* $Id: r4xx0.c,v 1.19 1996/08/02 11:11:36 dm Exp $
+ * 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/segment.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"
+ "sd\t%2,-16(%0)\n\t"
+ "sd\t%3,-12(%0)\n\t"
+ "sd\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\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"
+ "sd\t%2,-16(%0)\n\t"
+ "sd\t%3,-12(%0)\n\t"
+ "sd\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\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 inline struct vm_area_struct *
+find_mm_vma(struct mm_struct *mm, unsigned long addr)
+{
+ struct vm_area_struct * result = NULL;
+
+ if (mm) {
+ struct vm_area_struct * tree = mm->mmap_avl;
+ for (;;) {
+ if (tree == avl_empty)
+ break;
+ if (tree->vm_end > addr) {
+ result = tree;
+ if (tree->vm_start <= addr)
+ break;
+ tree = tree->vm_avl_left;
+ } else
+ tree = tree->vm_avl_right;
+ }
+ }
+ return result;
+}
+
+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_mm_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_mm_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_mm_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_mm_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_mm_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_mm_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_mm_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_mm_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, tmp1, tmp2;
+
+#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
+ /*
+ * 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);
+ flush_tlb_all();
+}
diff --git a/arch/mips/mm/r6000.c b/arch/mips/mm/r6000.c
new file mode 100644
index 000000000..ad9332d3f
--- /dev/null
+++ b/arch/mips/mm/r6000.c
@@ -0,0 +1,182 @@
+/* $Id: r6000.c,v 1.5 1996/07/29 11:10:08 dm 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/segment.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/stack.c b/arch/mips/mm/stack.c
deleted file mode 100644
index 3a4dccd26..000000000
--- a/arch/mips/mm/stack.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Kernel stack allocation/deallocation
- *
- * 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 is _bad_ if the free page pool is fragmented ...)
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-extern unsigned long alloc_kernel_stack(void)
-{
- unsigned long stack;
- stack = __get_free_pages(GFP_KERNEL, 1, 0);
-
- return stack;
-}
-
-extern void free_kernel_stack(unsigned long stack)
-{
- free_pages(stack, 1);
-}
diff --git a/arch/mips/mm/tfp.c b/arch/mips/mm/tfp.c
new file mode 100644
index 000000000..9bd7f2b4a
--- /dev/null
+++ b/arch/mips/mm/tfp.c
@@ -0,0 +1,103 @@
+/* $Id: tfp.c,v 1.3 1996/07/29 11:10:08 dm 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/segment.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/.cvsignore b/arch/mips/sgi/kernel/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/sgi/kernel/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
new file mode 100644
index 000000000..c79023b23
--- /dev/null
+++ b/arch/mips/sgi/kernel/Makefile
@@ -0,0 +1,30 @@
+# $Id: Makefile,v 1.5 1996/06/08 12:08:38 dm 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
index 000000000..a7058d3ee
--- /dev/null
+++ b/arch/mips/sgi/kernel/indyIRQ.S
@@ -0,0 +1,138 @@
+/* $Id: indyIRQ.S,v 1.5 1996/06/29 12:41:12 dm 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
+ lui s3, %hi(intr_count)
+
+ /* 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. */
+ lw s7, %lo(intr_count)(s3)
+ move a0, sp
+ addiu t0, s7, 1
+ jal indy_timer_interrupt
+ sw t0, %lo(intr_count)(s3) # delay slot, set intr_count
+
+ j ret_from_sys_call
+ sw s7, %lo(intr_count)(s3) # delay slot, restore intr_count
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
+
+ /* Wheee, local level zero interrupt. */
+ lw s7, %lo(intr_count)(s3)
+ move a0, sp
+ addiu t0, s7, 1
+
+ jal indy_local0_irqdispatch
+ sw t0, %lo(intr_count)(s3)
+
+ j ret_from_sys_call
+ sw s7, %lo(intr_count)(s3) # delay slot, restore intr_count
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
+
+ /* Wheee, local level one interrupt. */
+ lw s7, %lo(intr_count)(s3)
+ move a0, sp
+ addiu t0, s7, 1
+ jal indy_local1_irqdispatch
+ sw t0, %lo(intr_count)(s3)
+
+ j ret_from_sys_call
+ sw s7, %lo(intr_count)(s3)
+
+1:
+ beq a0, zero, 1f
+ lw s7, %lo(intr_count)(s3)
+
+ /* Wheee, an asynchronous bus error... */
+ addiu t0, s7, 1
+ move a0, sp
+ jal indy_buserror_irq
+ sw t0, %lo(intr_count)(s3)
+
+ j ret_from_sys_call
+ sw s7, %lo(intr_count)(s3)
+
+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
+ sw t0, %lo(intr_count)(s3)
+1:
+ j ret_from_sys_call
+ sw s7, %lo(intr_count)(s3)
+ END(indyIRQ)
diff --git a/arch/mips/sgi/kernel/indy_hpc.c b/arch/mips/sgi/kernel/indy_hpc.c
new file mode 100644
index 000000000..30f3fe36b
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_hpc.c
@@ -0,0 +1,114 @@
+/* $Id: indy_hpc.c,v 1.4 1996/06/29 07:06:50 dm Exp $
+ * indy_hpc.c: Routines for generic manipulation of the HPC controllers.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/segment.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
index 000000000..45600d2de
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_int.c
@@ -0,0 +1,579 @@
+/* $Id: indy_int.c,v 1.12 1996/08/07 02:54:11 dm 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 <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/segment.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 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?");
+ }
+}
+
+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);
+}
+
+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;
+}
+
+/*
+ * 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);
+ 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;
+ }
+}
+
+/*
+ * 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);
+
+ 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;
+ }
+}
+
+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
index 000000000..b2f35018c
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_mc.c
@@ -0,0 +1,153 @@
+/* $Id: indy_mc.c,v 1.5 1996/06/29 07:06:51 dm Exp $
+ * indy_mc.c: Routines for manipulating the INDY memory controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/segment.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
index 000000000..9aa88cb18
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_timer.c
@@ -0,0 +1,298 @@
+/* $Id: indy_timer.c,v 1.10 1996/08/07 02:54:11 dm 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/segment.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
index 000000000..4e7455952
--- /dev/null
+++ b/arch/mips/sgi/kernel/reset.c
@@ -0,0 +1,14 @@
+/*
+ * linux/arch/mips/sgi/kernel/process.c
+ *
+ * Reset a SGI.
+ */
+#include <asm/io.h>
+#include <asm/system.h>
+
+void
+sgi_hard_reset_now(void)
+{
+ for(;;)
+ prom_imode();
+}
diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c
new file mode 100644
index 000000000..61b67df75
--- /dev/null
+++ b/arch/mips/sgi/kernel/setup.c
@@ -0,0 +1,83 @@
+/* $Id: setup.c,v 1.11 1996/06/29 07:06:51 dm 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/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 */
+
+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;
+ hard_reset_now = acn_hard_reset_now;
+
+ /* 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
index 000000000..051ad09c5
--- /dev/null
+++ b/arch/mips/sgi/kernel/system.c
@@ -0,0 +1,168 @@
+/* $Id: system.c,v 1.2 1996/06/10 16:38:32 dm 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
index 000000000..1f5137c27
--- /dev/null
+++ b/arch/mips/sgi/kernel/time.c
@@ -0,0 +1,14 @@
+/* $Id: time.c,v 1.1 1996/06/08 12:07:08 dm 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/.cvsignore b/arch/mips/sgi/prom/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/arch/mips/sgi/prom/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/arch/mips/sgi/prom/Makefile b/arch/mips/sgi/prom/Makefile
new file mode 100644
index 000000000..8dbfedf80
--- /dev/null
+++ b/arch/mips/sgi/prom/Makefile
@@ -0,0 +1,23 @@
+# $Id: Makefile,v 1.6 1996/06/08 04:48:41 dm 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
index 000000000..4c7da5e43
--- /dev/null
+++ b/arch/mips/sgi/prom/cmdline.c
@@ -0,0 +1,60 @@
+/* $Id: cmdline.c,v 1.1 1996/06/08 03:23:10 dm 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
index 000000000..3f4d69f45
--- /dev/null
+++ b/arch/mips/sgi/prom/console.c
@@ -0,0 +1,24 @@
+/* $Id: console.c,v 1.1 1996/06/04 00:57:05 dm 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
index 000000000..5aff47efd
--- /dev/null
+++ b/arch/mips/sgi/prom/env.c
@@ -0,0 +1,20 @@
+/* $Id: env.c,v 1.2 1996/06/08 04:48:41 dm 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
index 000000000..b62d33dda
--- /dev/null
+++ b/arch/mips/sgi/prom/file.c
@@ -0,0 +1,58 @@
+/* $Id: file.c,v 1.1 1996/06/08 04:47:22 dm 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
index 000000000..6b6167efd
--- /dev/null
+++ b/arch/mips/sgi/prom/init.c
@@ -0,0 +1,59 @@
+/* $Id: init.c,v 1.6 1996/06/10 16:38:33 dm 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
index 000000000..cb392a805
--- /dev/null
+++ b/arch/mips/sgi/prom/memory.c
@@ -0,0 +1,129 @@
+/* $Id: memory.c,v 1.5 1996/06/10 16:38:33 dm 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
index 000000000..47051a1b3
--- /dev/null
+++ b/arch/mips/sgi/prom/misc.c
@@ -0,0 +1,109 @@
+/* $Id: misc.c,v 1.3 1996/08/07 02:54:12 dm Exp $
+ * misc.c: Miscellaneous ARCS PROM routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#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();
+ reset_wd33c93(sgiwd93_host);
+ cli();
+ romvec->halt();
+}
+
+void prom_powerdown(void)
+{
+ shutoff_r4600_cache();
+ initialize_kbd();
+ reset_wd33c93(sgiwd93_host);
+ cli();
+ romvec->pdown();
+}
+
+/* XXX is this a soft reset basically? XXX */
+void prom_restart(void)
+{
+ shutoff_r4600_cache();
+ initialize_kbd();
+ reset_wd33c93(sgiwd93_host);
+ cli();
+ romvec->restart();
+}
+
+void prom_reboot(void)
+{
+ shutoff_r4600_cache();
+ initialize_kbd();
+ reset_wd33c93(sgiwd93_host);
+ cli();
+ romvec->reboot();
+}
+
+void prom_imode(void)
+{
+ shutoff_r4600_cache();
+ initialize_kbd();
+ reset_wd33c93(sgiwd93_host);
+ 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
index 000000000..02e7e4734
--- /dev/null
+++ b/arch/mips/sgi/prom/printf.c
@@ -0,0 +1,34 @@
+/* $Id: printf.c,v 1.1 1996/06/04 00:57:06 dm 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
index 000000000..4f120af3a
--- /dev/null
+++ b/arch/mips/sgi/prom/salone.c
@@ -0,0 +1,24 @@
+/* $Id: salone.c,v 1.1 1996/06/08 04:47:22 dm 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
index 000000000..4a9fe0b2b
--- /dev/null
+++ b/arch/mips/sgi/prom/tags.c
@@ -0,0 +1,67 @@
+/* $Id: tags.c,v 1.5 1996/06/24 07:12:22 dm 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/segment.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
index 000000000..9a836b810
--- /dev/null
+++ b/arch/mips/sgi/prom/time.c
@@ -0,0 +1,17 @@
+/* $Id: time.c,v 1.1 1996/06/08 04:47:23 dm 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
index 000000000..1cefd4964
--- /dev/null
+++ b/arch/mips/sgi/prom/tree.c
@@ -0,0 +1,107 @@
+/* $Id: tree.c,v 1.4 1996/06/08 04:48:41 dm 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
index bfa8e2cad..3821d7b62 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -11,16 +11,10 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-include ../../../.config
-
all: sni.o
O_TARGET := sni.o
O_OBJS := hw-access.o int-handler.o reset.o setup.o
-ifdef CONFIG_PCI
-O_OBJS += bios32.o
-endif
-
int-handler.o: int-handler.S
clean:
diff --git a/arch/mips/sni/bios32.c b/arch/mips/sni/bios32.c
deleted file mode 100644
index 366347902..000000000
--- a/arch/mips/sni/bios32.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * bios32.c - Fake PCI BIOS functions for RM200 C systems. Chainsawed
- * from the Alpha version.
- *
- * Written by Ralf Baechle (ralf@gnu.ai.mit.edu)
- *
- * For more information, please consult
- *
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000
- * +1 (800) 433-5177
- *
- * Manuals are $25 each or $50 for all three, plus $7 shipping
- * within the United States, $35 abroad.
- */
-#include <linux/config.h>
-
-#include <linux/kernel.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-/*
- * This is a table of the onboard PCI devices of the RM200 C
- * onboard devices.
- */
-static struct board {
- unsigned short vendor;
- unsigned short device_id;
- unsigned int memory;
- unsigned int io;
- unsigned char irq;
- unsigned char revision;
- } boards[] = {
- {
- PCI_VENDOR_ID_NCR,
- PCI_DEVICE_ID_NCR_53C810,
- 0x1b000000,
- 0x00000000,
- 5,
- 0x11
- },
- {
- PCI_VENDOR_ID_AMD,
- PCI_DEVICE_ID_AMD_LANCE,
- 0x1b000100,
- 0x17beffe0,
- 6,
- 0x16
- },
- {
- PCI_VENDOR_ID_CIRRUS,
- PCI_DEVICE_ID_CIRRUS_5434_8,
- 0x18000000,
- 0x00000000,
- 4,
- 0x8e
- },
- { 0xffff, }
-};
-
-/*
- * 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 board *p;
-
- for (p = pci_devices; p->vendor != 0xffff; p++) {
- if (p->vendor == vendor && p->device == device_id) {
- if (curr == index) {
- *devfn = p->devfn;
- *bus = 0;
- 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;
-}
-
-int pcibios_present(void)
-{
- return 1;
-}
-
-unsigned long pcibios_init(unsigned long mem_start,
- unsigned long mem_end)
-{
- printk("SNI RM200 C BIOS32 fake implementation\n");
-
- return mem_start;
-}
-
-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;
- }
-}
-
-/*
- * BIOS32-style PCI interface:
- */
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x00;
- *value = conf_read(addr) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x08;
- *value = conf_read(addr) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xffffffff;
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- *value = conf_read(addr);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x00;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
diff --git a/arch/mips/sni/hw-access.c b/arch/mips/sni/hw-access.c
index 42c69590a..39cbec410 100644
--- a/arch/mips/sni/hw-access.c
+++ b/arch/mips/sni/hw-access.c
@@ -11,12 +11,14 @@
#include <linux/kernel.h>
#include <linux/linkage.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/bootinfo.h>
-#include <asm/cache.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;
@@ -109,7 +111,7 @@ fd_disable_irq(void)
void
sni_fd_cacheflush(const void *addr, size_t size)
{
- cacheflush((unsigned long)addr, (unsigned long)size, CF_DCACHE|CF_ALL);
+ flush_cache_all();
}
/*
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
index 367c07d84..c01c34c9d 100644
--- a/arch/mips/sni/int-handler.S
+++ b/arch/mips/sni/int-handler.S
@@ -12,21 +12,22 @@
#include <asm/mipsconfig.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
+#include <asm/sni.h>
#include <asm/stackframe.h>
.text
.set noreorder
.set noat
.align 5
- NESTED(sni_rm200_pci_handle_int, FR_SIZE, sp)
+ NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
SAVE_ALL
- REG_S sp,FR_ORIG_REG2(sp)
+ REG_S sp,PT_OR2(sp)
CLI
.set at
- lui s0,%hi(PORT_BASE_SNI)
+ lui s0,%hi(SNI_PORT_BASE)
li a0,0x0f
- sb a0,%lo(PORT_BASE_SNI+0x20)(s0) # poll command
- lb a0,%lo(PORT_BASE_SNI+0x20)(s0) # read result
+ 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?
@@ -34,17 +35,17 @@
/*
* Acknowledge first pic
*/
- lb t2,%lo(PORT_BASE_SNI+0x21)(s0)
+ 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(PORT_BASE_SNI+0x21)(s0)
+ sb t0,%lo(SNI_PORT_BASE+0x21)(s0)
lui s3,%hi(intr_count)
lw s7,%lo(intr_count)(s3)
li t2,0x20
- sb t2,%lo(PORT_BASE_SNI+0x20)(s0)
+ sb t2,%lo(SNI_PORT_BASE+0x20)(s0)
/*
* Now call the real handler
*/
@@ -59,38 +60,38 @@
/*
* Unblock first pic
*/
- lbu t1,%lo(PORT_BASE_SNI+0x21)(s0)
+ 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(PORT_BASE_SNI+0x21)(s0) # delay slot
+ 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(PORT_BASE_SNI+0xa0)(s0) # poll command
- lb a0,%lo(PORT_BASE_SNI+0xa0)(s0) # read result
+ 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(PORT_BASE_SNI+0xa1)(s0)
+ 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(PORT_BASE_SNI+0xa1)(s0)
+ sb t3,%lo(SNI_PORT_BASE+0xa1)(s0)
li t3,0x20
- sb t3,%lo(PORT_BASE_SNI+0xa0)(s0)
+ sb t3,%lo(SNI_PORT_BASE+0xa0)(s0)
lui s3,%hi(intr_count)
lw s7,%lo(intr_count)(s3)
- sb t3,%lo(PORT_BASE_SNI+0x20)(s0)
+ sb t3,%lo(SNI_PORT_BASE+0x20)(s0)
/*
* Now call the real handler
*/
@@ -106,14 +107,14 @@ poll_second: li a0,0x0f
/*
* Unblock second pic
*/
- lb t1,%lo(PORT_BASE_SNI+0xa1)(s0)
+ 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(PORT_BASE_SNI+0xa1)(s0) # delay slot
+ sb t1,%lo(SNI_PORT_BASE+0xa1)(s0) # delay slot
/*
* FIXME: This is definatly wrong but I'll have to do it this way
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index a4cc4a57f..ca958ca2a 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -16,6 +16,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
+#include <asm/sni.h>
#include <asm/vector.h>
/*
@@ -93,7 +94,7 @@ sni_rm200_pci_setup(void)
irq_setup = sni_irq_setup;
fd_cacheflush = sni_fd_cacheflush; // Will go away
feature = &sni_rm200_pci_feature;
- port_base = PORT_BASE_SNI;
+ port_base = SNI_PORT_BASE;
isa_slot_offset = 0xb0000000;
request_region(0x00,0x20,"dma1");
request_region(0x40,0x20,"timer");
diff --git a/arch/mips/tools/Makefile b/arch/mips/tools/Makefile
new file mode 100644
index 000000000..7216277b3
--- /dev/null
+++ b/arch/mips/tools/Makefile
@@ -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
index 000000000..3bb46de6e
--- /dev/null
+++ b/arch/mips/tools/offset.c
@@ -0,0 +1,128 @@
+/*
+ * 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_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_SAVED_KSTACK ", struct task_struct, saved_kernel_stack);
+ offset("#define TASK_KSTACK_PG ", struct task_struct, kernel_stack_page);
+ offset("#define TASK_MM ", struct task_struct, mm);
+ linefeed;
+}
+
+void output_thread_defines(void)
+{
+ text("/* MIPS specific thread_struct offsets. */");
+ offset("#define THREAD_REG16 ", struct task_struct, tss.reg16);
+ offset("#define THREAD_REG17 ", struct task_struct, tss.reg17);
+ offset("#define THREAD_REG18 ", struct task_struct, tss.reg18);
+ offset("#define THREAD_REG19 ", struct task_struct, tss.reg19);
+ offset("#define THREAD_REG20 ", struct task_struct, tss.reg20);
+ offset("#define THREAD_REG21 ", struct task_struct, tss.reg21);
+ offset("#define THREAD_REG22 ", struct task_struct, tss.reg22);
+ offset("#define THREAD_REG23 ", struct task_struct, tss.reg23);
+ offset("#define THREAD_REG28 ", struct task_struct, tss.reg28);
+ offset("#define THREAD_REG29 ", struct task_struct, tss.reg29);
+ offset("#define THREAD_REG30 ", struct task_struct, tss.reg30);
+ offset("#define THREAD_REG31 ", struct task_struct, tss.reg31);
+ offset("#define THREAD_STATUS ", struct task_struct, tss.cp0_status);
+ offset("#define THREAD_FPU ", struct task_struct, tss.fpu);
+ offset("#define THREAD_BVADDR ", struct task_struct, tss.cp0_badvaddr);
+ offset("#define THREAD_ECODE ", struct task_struct, tss.error_code);
+ offset("#define THREAD_TRAPNO ", struct task_struct, tss.trap_no);
+ offset("#define THREAD_KSP ", struct task_struct, tss.ksp);
+ offset("#define THREAD_PGDIR ", struct task_struct, tss.pg_dir);
+ offset("#define THREAD_MFLAGS ", struct task_struct, tss.mflags);
+ offset("#define THREAD_CURDS ", struct task_struct, tss.current_ds);
+ offset("#define THREAD_TRAMP ", struct task_struct, tss.irix_trampoline);
+ offset("#define THREAD_OLDCTX ", struct task_struct, tss.irix_oldctx);
+ linefeed;
+}
+
+void output_mm_defines(void)
+{
+ text("/* Linux mm_struct offsets. */");
+ offset("#define MM_COUNT ", struct mm_struct, count);
+ offset("#define MM_PGD ", struct mm_struct, pgd);
+ offset("#define MM_CONTEXT ", struct mm_struct, context);
+ linefeed;
+}
+
+text("#endif /* !(_MIPS_OFFSET_H) */");
diff --git a/arch/mips/tools/offset.h b/arch/mips/tools/offset.h
new file mode 100644
index 000000000..c5e6f37fa
--- /dev/null
+++ b/arch/mips/tools/offset.h
@@ -0,0 +1,89 @@
+/* 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_PRIORITY 8
+#define TASK_SIGNAL 12
+#define TASK_BLOCKED 16
+#define TASK_FLAGS 20
+#define TASK_SAVED_KSTACK 84
+#define TASK_KSTACK_PG 88
+#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 0
+#define MM_PGD 4
+#define MM_CONTEXT 8
+
+#endif /* !(_MIPS_OFFSET_H) */
diff --git a/drivers/Makefile b/drivers/Makefile
index 600ff70ea..4274df602 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -9,7 +9,7 @@
SUB_DIRS := block char net #streams
MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci sbus scsi sound cdrom isdn
+ALL_SUB_DIRS := $(SUB_DIRS) pci sbus sgi scsi sound cdrom isdn
ifdef CONFIG_PCI
SUB_DIRS += pci
@@ -19,6 +19,10 @@ ifdef CONFIG_SBUS
SUB_DIRS += sbus
endif
+ifdef CONFIG_SGI
+SUB_DIRS += sgi
+endif
+
# If CONFIG_SCSI is set, the core of scsi support will be added to the kernel,
# but some of the low-level things may also be modules.
ifeq ($(CONFIG_SCSI),y)
diff --git a/drivers/block/.cvsignore b/drivers/block/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/block/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 7179c6f33..bc77f31f8 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -151,6 +151,7 @@ static int use_virtual_dma=0; /* virtual DMA for Intel */
static unsigned short virtual_dma_port=0x3f0;
void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static int set_dor(int fdc, char mask, char data);
+static inline int __get_order(unsigned long size);
#include <asm/floppy.h>
@@ -170,6 +171,20 @@ static int set_dor(int fdc, char mask, char data);
/* Dma Memory related stuff */
+/* Pure 2^n version of get_order */
+static 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;
+}
+
#ifndef fd_dma_mem_free
#define fd_dma_mem_free(addr, size) free_pages(addr, __get_order(size))
#endif
@@ -1207,6 +1222,7 @@ static void fdc_specify(void)
/*DPRINT("FIFO enabled\n");*/
}
+#ifndef __sparc__
switch (raw_cmd->rate & 0x03) {
case 3:
dtr = 1000;
@@ -1261,6 +1277,7 @@ static void fdc_specify(void)
output_byte(FDCS->spec1 = spec1);
output_byte(FDCS->spec2 = spec2);
}
+#endif
} /* fdc_specify */
/* Set the FDC's data transfer rate on behalf of the specified drive.
@@ -1534,7 +1551,8 @@ static void seek_floppy(void)
(raw_cmd->flags & FD_RAW_NEED_SEEK))
track = raw_cmd->track;
else {
- setup_rw_floppy(); return;
+ setup_rw_floppy();
+ return;
}
}
@@ -1661,9 +1679,9 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
if (handler) {
if(intr_count >= 2)
- schedule_bh( (void *)(void *) handler);
+ schedule_bh( (void *)(void *) handler);
else
- handler();
+ handler();
} else
FDCS->reset = 1;
is_alive("normal interrupt end");
@@ -1709,7 +1727,7 @@ static void reset_fdc(void)
/* Irrelevant for systems with true DMA (i386). */
fd_disable_dma();
- if (FDCS->version >= FDC_82077)
+ if (FDCS->version >= FDC_82072A)
fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS);
else {
fd_outb(FDCS->dor & ~0x04, FD_DOR);
@@ -2748,8 +2766,7 @@ static void process_fd_request(void)
static void do_fd_request(void)
{
if(usage_count == 0) {
- printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
- printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
+ printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);+ printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
return;
}
sti();
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 198e4a483..85a0ca3c7 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -15,8 +15,6 @@
*
* More flexible handling of extended partitions - aeb, 950831
*
- * Support for systems without PC-style consoles - <dfrick@dial.eunet.ch>, 960+ *
- *
* Check partition table on IDE disks for common CHS translations
*/
@@ -39,9 +37,9 @@
*/
#include <asm/unaligned.h>
-#define SYS_IND(p) get_unaligned(&p->sys_ind)
-#define NR_SECTS(p) get_unaligned(&p->nr_sects)
-#define START_SECT(p) get_unaligned(&p->start_sect)
+#define SYS_IND(p) get_unaligned(&p->sys_ind)
+#define NR_SECTS(p) get_unaligned(&p->nr_sects)
+#define START_SECT(p) get_unaligned(&p->start_sect)
struct gendisk *gendisk_head = NULL;
@@ -245,7 +243,6 @@ static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
{
int i, minor = current_minor;
struct buffer_head *bh;
- struct partition ptable[4];
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
@@ -270,8 +267,7 @@ check_table:
brelse(bh);
return 0;
}
- memcpy(ptable, (struct partition *)(data + 0x1be), sizeof(struct partition) * 4);
- p = ptable;
+ p = (struct partition *) (0x1be + data);
#ifdef CONFIG_BLK_DEV_IDE
if (!tested_for_xlate++) { /* Do this only once per disk */
@@ -378,7 +374,7 @@ check_table:
* Check for old-style Disk Manager partition table
*/
if (*(unsigned short *) (data+0xfc) == 0x55AA) {
- p = ptable;
+ p = (struct partition *) (0x1be + data);
for (i = 4 ; i < 16 ; i++, current_minor++) {
p--;
if ((current_minor & mask) == 0)
@@ -556,6 +552,74 @@ static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec
#endif /* CONFIG_SUN_PARTITION */
+#ifdef CONFIG_SGI_PARTITION
+
+static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+ int i, csum;
+ unsigned int *ui;
+ struct buffer_head *bh;
+ struct sgi_disklabel {
+ int magic_mushroom; /* Big fat spliff... */
+ short root_part_num; /* Root partition number */
+ short swap_part_num; /* Swap partition number */
+ char boot_file[16]; /* Name of boot file for ARCS */
+ unsigned char _unused0[48]; /* Device parameter useless crapola.. */
+ struct sgi_volume {
+ char name[8]; /* Name of volume */
+ int block_num; /* Logical block number */
+ int num_bytes; /* How big, in bytes */
+ } volume[15];
+ struct sgi_partition {
+ int num_blocks; /* Size in logical blocks */
+ int first_block; /* First logical block */
+ int type; /* Type of this partition */
+ } partitions[16];
+ int csum; /* Disk label checksum */
+ int _unused1; /* Padding */
+ } *label;
+ struct sgi_partition *p;
+#define SGI_LABEL_MAGIC 0x0be5a941
+
+ if(!(bh = bread(dev, 0, 1024))) {
+ printk("Dev %s: unable to read partition table\n", kdevname(dev));
+ return -1;
+ }
+ label = (struct sgi_disklabel *) bh->b_data;
+ p = &label->partitions[0];
+ if(label->magic_mushroom != SGI_LABEL_MAGIC) {
+ printk("Dev %s SGI disklabel: bad magic %08x\n",
+ kdevname(dev), label->magic_mushroom);
+ brelse(bh);
+ return 0;
+ }
+ ui = ((unsigned int *) (label + 1)) - 1;
+ for(csum = 0; ui >= ((unsigned int *) label);)
+ csum += *ui--;
+ if(csum) {
+ printk("Dev %s SGI disklabel: csum bad, label corrupted\n",
+ kdevname(dev));
+ brelse(bh);
+ return 0;
+ }
+ /* All SGI disk labels have 16 partitions, disks under Linux only
+ * have 15 minor's. Luckily there are always a few zero length
+ * partitions which we don't care about so we never overflow the
+ * current_minor.
+ */
+ for(i = 0; i < 16; i++, p++) {
+ if(!(p->num_blocks))
+ continue;
+ add_partition(hd, current_minor, p->first_block, p->num_blocks);
+ current_minor++;
+ }
+ printk("\n");
+ brelse(bh);
+ return 1;
+}
+
+#endif
+
#ifdef CONFIG_AMIGA_PARTITION
#include <asm/byteorder.h>
#include <linux/affs_hardblocks.h>
@@ -675,6 +739,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
if(amiga_partition(hd, dev, first_sector))
return;
#endif
+#ifdef CONFIG_SGI_PARTITION
+ if(sgi_partition(hd, dev, first_sector))
+ return;
+#endif
printk(" unknown partition table\n");
}
@@ -746,9 +814,7 @@ void device_setup(void)
#ifdef CONFIG_INET
net_dev_init();
#endif
-#ifndef CONFIG_SERIAL_ONLY_CONSOLE
console_map_init();
-#endif
for (p = gendisk_head ; p ; p=p->next) {
setup_dev(p);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index e7ad12604..bc2206737 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -3,7 +3,6 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, Karl Keyte: Added support for disk statistics
- * Copyright (C) 1996, ACN S.A: Added support for flash devices
*/
/*
@@ -650,10 +649,9 @@ int blk_dev_init(void)
#ifdef CONFIG_BLK_DEV_FD
floppy_init();
#else
+#ifndef CONFIG_SGI
outb_p(0xc, 0x3f2);
#endif
-#ifdef CONFIG_ACN_MIPS_BOARD
- flash_devs_init();
#endif
#ifdef CONFIG_CDU31A
cdu31a_init();
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 0150bf404..f1bfa7403 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -35,7 +35,6 @@
*
* 4/25/96 : Made ramdisk size a parameter (default is now 4MB)
* - Chad Page
- * 7/23/96 : Support for systems without PC-style consoles - <dfrick@dial.eunet.ch>
*/
#include <linux/config.h>
@@ -521,11 +520,9 @@ void rd_load()
#ifdef CONFIG_BLK_DEV_FD
floppy_eject();
#endif
-#ifndef CONFIG_SERIAL_ONLY_CONSOLE
printk(KERN_NOTICE
"VFS: Insert root floppy disk to be loaded into ramdisk and press ENTER\n");
wait_for_keypress();
-#endif
}
rd_load_image(ROOT_DEV,rd_image_start);
diff --git a/drivers/cdrom/.cvsignore b/drivers/cdrom/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/cdrom/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/char/.cvsignore b/drivers/char/.cvsignore
new file mode 100644
index 000000000..1b9baceaa
--- /dev/null
+++ b/drivers/char/.cvsignore
@@ -0,0 +1,3 @@
+.depend
+conmakehash
+uni_hash.tbl
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 8bb627372..662660f10 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -26,7 +26,9 @@ L_OBJS := tty_io.o n_tty.o console.o \
ifeq ($(CONFIG_SERIAL),y)
ifndef CONFIG_SUN_SERIAL
- LX_OBJS += serial.o
+ ifndef CONFIG_SGI_SERIAL
+ LX_OBJS += serial.o
+ endif
endif
else
ifeq ($(CONFIG_SERIAL),m)
@@ -201,7 +203,9 @@ L_OBJS += tga.o
else
ifndef CONFIG_SUN_CONSOLE
ifndef CONFIG_VIDEO_G364
- L_OBJS += vga.o vesa_blank.o
+ ifndef CONFIG_SGI
+ L_OBJS += vga.o vesa_blank.o
+ endif
endif
endif
endif
diff --git a/drivers/char/console.c b/drivers/char/console.c
index 070dc9bf3..750fd96f7 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -105,7 +105,9 @@
#include <linux/apm_bios.h>
#endif
-#ifdef __mips__
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#elif defined(CONFIG_ACER_PICA_61)
#include <asm/bootinfo.h>
/*
* The video control ports are mapped at virtual address
@@ -130,6 +132,8 @@ unsigned long video_port_base;
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
+int serial_console;
+
struct tty_driver console_driver;
static int console_refcount;
static struct tty_struct *console_table[MAX_NR_CONSOLES];
@@ -165,6 +169,9 @@ extern void set_palette(void);
extern unsigned long con_type_init(unsigned long, const char **);
extern int set_get_cmap(unsigned char *, int);
extern int set_get_font(unsigned char *, int, int);
+#ifdef CONFIG_SGI
+extern void rs_cons_hook(int chip, int out, int channel);
+#endif
/* Description of the hardware situation */
unsigned char video_type; /* Type of display being used */
@@ -597,7 +604,7 @@ static void set_origin(int currcons)
{
if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_VGAC &&
video_type != VIDEO_TYPE_EGAM && video_type != VIDEO_TYPE_PICA_S3 &&
- video_type != VIDEO_TYPE_SNI_RM)
+ video_type != VIDEO_TYPE_SNI_RM && video_type != VIDEO_TYPE_SGI)
return;
if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
return;
@@ -629,7 +636,7 @@ void scrup(int currcons, unsigned int t, unsigned int b)
/*
* Is the end of the area to scroll outside of the video RAM?
* If so, just do normal softscroll. The second part of the
- * expression is important for some non-Intel architectures.
+ * condition is important for some non-Intel architectures.
*/
if (scr_end > video_mem_end || scr_end < video_mem_base) {
unsigned short * d = (unsigned short *) video_mem_start;
@@ -898,7 +905,7 @@ static void csi_m(int currcons)
toggle_meta = 0;
break;
case 11: /* ANSI X3.64-1979 (SCO-ish?)
- * Select first alternate font, lets
+ * Select first alternate font, let's
* chars < 32 be displayed as ROM chars.
*/
translate = set_translate(IBMPC_MAP);
@@ -2053,6 +2060,17 @@ unsigned long con_init(unsigned long kmem_start)
int orig_x = ORIG_X;
int orig_y = ORIG_Y;
+#ifdef CONFIG_SGI
+ if (serial_console) {
+ fg_console = 0;
+
+ rs_cons_hook(0, 0, serial_console);
+ rs_cons_hook(0, 1, serial_console);
+
+ return kmem_start;
+ }
+#endif
+
memset(&console_driver, 0, sizeof(struct tty_driver));
console_driver.magic = TTY_DRIVER_MAGIC;
console_driver.name = "tty";
@@ -2099,7 +2117,7 @@ unsigned long con_init(unsigned long kmem_start)
|| video_type == VIDEO_TYPE_VGAC
|| video_type == VIDEO_TYPE_EGAM
|| video_type == VIDEO_TYPE_PICA_S3
- || video_type == VIDEO_TYPE_SNI_RM));
+ || video_type == VIDEO_TYPE_SNI_RM ));
has_wrapped = 0 ;
/* Due to kmalloc roundup allocating statically is more efficient -
@@ -2139,7 +2157,8 @@ unsigned long con_init(unsigned long kmem_start)
printable = 1;
if ( video_type == VIDEO_TYPE_VGAC || video_type == VIDEO_TYPE_EGAC
- || video_type == VIDEO_TYPE_EGAM || video_type == VIDEO_TYPE_TGAC )
+ || video_type == VIDEO_TYPE_EGAM || video_type == VIDEO_TYPE_TGAC
+ || video_type == VIDEO_TYPE_SGI )
{
default_font_height = video_font_height = ORIG_VIDEO_POINTS;
/* This may be suboptimal but is a safe bet - go with it */
diff --git a/drivers/char/ftape/.cvsignore b/drivers/char/ftape/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/char/ftape/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index dc40910b4..36ef2bacb 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -16,10 +16,8 @@
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
*/
-#define DISABLE_KBD_DURING_INTERRUPTS 0
-
+#include <linux/config.h>
#include <linux/kbdcntrlr.h>
-#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
@@ -47,7 +45,6 @@ static int send_data(unsigned char data);
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
-#define KBD_REPORT_ERR
#define KBD_REPORT_UNKN
/* #define KBD_IS_FOCUS_9000 */
@@ -332,6 +329,10 @@ int getkeycode(unsigned int scancode)
e0_keys[scancode - 128];
}
+#if defined(CONFIG_SGI) && defined(CONFIG_PSMOUSE)
+extern void aux_interrupt(unsigned char status, unsigned char data);
+#endif
+
#if DISABLE_KBD_DURING_INTERRUPTS
#define disable_keyboard() do { send_cmd(0xAD); kb_wait(); } while (0)
#define enable_keyboard() send_cmd(0xAE)
@@ -583,8 +584,13 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned char scancode;
/* mouse data? */
- if (status & kbd_read_mask & 0x20)
+ if (status & kbd_read_mask & 0x20) {
+#if defined(CONFIG_SGI) && defined(CONFIG_PSMOUSE)
+ scancode = kbd_inb(0x60);
+ aux_interrupt(status, scancode);
+#endif
break;
+ }
scancode = kbd_inb(0x60);
if (status & 0x01)
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 40ad1712f..281226f69 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -6,14 +6,12 @@
* Copyright (C) 1993 by Nigel Gamble (added interrupt code)
* Copyright (C) 1994 by Alan Cox (Modularised it)
* LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
- * Mips JAZZ support by Andreas Busse, andy@waldorf-gmbh.de
* Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
* "lp=" command line parameters added by Grant Guenther, grant@torque.net
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
@@ -27,9 +25,6 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#ifdef CONFIG_MIPS_JAZZ
-# include <asm/jazz.h>
-#endif
/* the BIOS manuals say there can be up to 4 lpt devices
* but I have not seen a board where the 4th address is listed
@@ -38,13 +33,6 @@
* if you have more than 3 printers, remember to increase LP_NO
*/
struct lp_struct lp_table[] = {
-#ifdef CONFIG_MIPS_JAZZ
- { JAZZ_PARALLEL_BASE,
- 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
-#else
- { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
- { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
-#endif
{ 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
{ 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
{ 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
@@ -68,31 +56,6 @@ struct lp_struct lp_table[] = {
#undef LP_DEBUG
-#ifdef CONFIG_MIPS_JAZZ
-static inline unsigned int lp_in(unsigned int port)
-{
-/* printk("lp_in: port>>24 = %08x, JAZZ_LOCAL_IO_SPACE >> 24 = %08x\n",
- port >> 24,JAZZ_LOCAL_IO_SPACE >> 24); */
- if (port >= JAZZ_LOCAL_IO_SPACE)
- return (*(volatile unsigned char *)port);
- else
- return inb_p(port);
-}
-
-static inline void lp_out(unsigned char value, unsigned int port)
-{
-/* printk("lp_out: port>>24 = %08x, JAZZ_LOCAL_IO_SPACE >> 24 = %08x\n",
- port >> 24,JAZZ_LOCAL_IO_SPACE >> 24); */
- if (port >= JAZZ_LOCAL_IO_SPACE)
- *(volatile unsigned char *)port = value;
- else
- outb(value, port);
-}
-#else
-#define lp_in(port) inb_p(port)
-#define lp_out(port,value) outb_p(port,value)
-#endif
-
static int lp_reset(int minor)
{
outb_p(LP_PSELECP, LP_C(minor));
@@ -101,10 +64,6 @@ static int lp_reset(int minor)
return LP_S(minor);
}
-#ifdef LP_DEBUG
-static int lp_max_count = 1;
-#endif
-
static inline int lp_char_polled(char lpchar, int minor)
{
int status, wait = 0;
@@ -122,17 +81,17 @@ static inline int lp_char_polled(char lpchar, int minor)
return 0;
/* we timed out, and the character was /not/ printed */
}
- lp_out(lpchar, LP_B(minor));
+ outb_p(lpchar, LP_B(minor));
stats = &LP_STAT(minor);
stats->chars++;
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
while(wait != LP_WAIT(minor)) wait++;
/* control port takes strobe high */
- lp_out(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
+ outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
while(wait) wait--;
/* take strobe low */
- lp_out(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
+ outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
/* update waittime statistics */
if (count > stats->maxwait) {
#ifdef LP_DEBUG
@@ -189,11 +148,6 @@ static inline int lp_char_interrupt(char lpchar, int minor)
return 0;
}
-#ifdef LP_DEBUG
- unsigned int lp_total_chars = 0;
- unsigned int lp_last_call = 0;
-#endif
-
static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct lp_struct *lp = &lp_table[0];
@@ -244,18 +198,18 @@ static inline int lp_write_interrupt(unsigned int minor, const char * buf, int c
}
LP_STAT(minor).sleeps++;
cli();
- lp_out((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
+ outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
status = LP_S(minor);
if ((!(status & LP_PACK) || (status & LP_PBUSY))
&& LP_CAREFUL_READY(minor, status)) {
- lp_out((LP_PSELECP|LP_PINITP), (LP_C(minor)));
+ outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
sti();
continue;
}
lp_table[minor].runchars=0;
current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
interruptible_sleep_on(&lp->lp_wait_q);
- lp_out((LP_PSELECP|LP_PINITP), (LP_C(minor)));
+ outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
sti();
if (current->signal & ~current->blocked) {
if (total_bytes_written + bytes_written)
diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c
index a6ba7bdaa..e0d92057b 100644
--- a/drivers/char/psaux.c
+++ b/drivers/char/psaux.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -49,6 +50,10 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#ifdef CONFIG_SGI
+#include <asm/segment.h>
+#include <asm/sgihpc.h>
+#endif
#include <linux/config.h>
@@ -93,6 +98,58 @@
#endif
#define AUX_BUF_SIZE 2048
+#ifdef CONFIG_SGI
+extern volatile struct hpc_keyb *kh; /* see keyboard.c */
+
+extern __inline__ int
+ps2_inb_p(unsigned short port)
+{
+ int result;
+
+ if(port == AUX_INPUT_PORT)
+ result = kh->data;
+ else if(port == AUX_STATUS)
+ result = kh->command;
+ return result;
+}
+
+extern __inline__ int
+ps2_inb(unsigned short port)
+{
+ int result;
+
+ if(port == AUX_INPUT_PORT)
+ result = kh->data;
+ else if(port == AUX_STATUS)
+ result = kh->command;
+
+ return result;
+}
+
+extern __inline__ void
+ps2_outb_p(unsigned char data, unsigned short port)
+{
+ if(port == AUX_OUTPUT_PORT)
+ kh->data = data;
+ else if(port == AUX_COMMAND)
+ kh->command = data;
+}
+
+extern __inline__ void
+ps2_outb(unsigned char data, unsigned short port)
+{
+ if(port == AUX_OUTPUT_PORT)
+ kh->data = data;
+ else if(port == AUX_COMMAND)
+ kh->command = data;
+}
+#else
+#define ps2_inb_p inb_p
+#define ps2_inb inb
+#define ps2_outb_p outb_p
+#define ps2_outb outb
+#endif
+
/* 82C710 definitions */
#define QP_DATA 0x310 /* Data Port I/O Address */
@@ -146,9 +203,9 @@ static int probe_qp(void);
static void aux_write_dev(int val)
{
poll_aux_status();
- outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); /* write magic cookie */
+ ps2_outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); /* write magic cookie */
poll_aux_status();
- outb_p(val,AUX_OUTPUT_PORT); /* write data */
+ ps2_outb_p(val,AUX_OUTPUT_PORT); /* write data */
}
/*
@@ -158,16 +215,16 @@ static void aux_write_dev(int val)
static int aux_write_ack(int val)
{
int retries = 0;
-
+
poll_aux_status_nosleep();
- outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
+ ps2_outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
poll_aux_status_nosleep();
- outb_p(val,AUX_OUTPUT_PORT);
+ ps2_outb_p(val,AUX_OUTPUT_PORT);
poll_aux_status_nosleep();
- if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
+ if ((ps2_inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
{
- return (inb(AUX_INPUT_PORT));
+ return (ps2_inb(AUX_INPUT_PORT));
}
return 0;
}
@@ -180,12 +237,11 @@ static int aux_write_ack(int val)
static void aux_write_cmd(int val)
{
poll_aux_status();
- outb_p(AUX_CMD_WRITE,AUX_COMMAND);
+ ps2_outb_p(AUX_CMD_WRITE,AUX_COMMAND);
poll_aux_status();
- outb_p(val,AUX_OUTPUT_PORT);
+ ps2_outb_p(val,AUX_OUTPUT_PORT);
}
-
static unsigned int get_from_queue(void)
{
unsigned int result;
@@ -211,16 +267,42 @@ static inline int queue_empty(void)
* Interrupt from the auxiliary device: a character
* is waiting in the keyboard/aux controller.
*/
-
+#ifndef CONFIG_SGI
static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
- if ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL)
+ if ((ps2_inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL)
+ return;
+
+ add_mouse_randomness(queue->buf[head] = ps2_inb(AUX_INPUT_PORT));
+ if (head != maxhead) {
+ head++;
+ head &= AUX_BUF_SIZE-1;
+ }
+ queue->head = head;
+ aux_ready = 1;
+ if (queue->fasync)
+ kill_fasync(queue->fasync, SIGIO);
+ wake_up_interruptible(&queue->proc_list);
+}
+#else
+/* On the SGI we export this routine because the keyboard chirps at
+ * the same interrupt level. The status and data bytes are passed
+ * directly to us if the keyboard interrupt service routine detects
+ * that the keyboard is not the cause of the interrupt, see keyboard.c
+ * for details.
+ */
+void aux_interrupt(unsigned char status, unsigned char data)
+{
+ int head = queue->head;
+ int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
+
+ if ((status & AUX_OBUF_FULL) != AUX_OBUF_FULL)
return;
- add_mouse_randomness(queue->buf[head] = inb(AUX_INPUT_PORT));
+ add_mouse_randomness(queue->buf[head] = data);
if (head != maxhead) {
head++;
head &= AUX_BUF_SIZE-1;
@@ -231,6 +313,7 @@ static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
kill_fasync(queue->fasync, SIGIO);
wake_up_interruptible(&queue->proc_list);
}
+#endif
/*
* Interrupt handler for the 82C710 mouse port. A character
@@ -266,11 +349,13 @@ static void release_aux(struct inode * inode, struct file * file)
disable_bh(KEYBOARD_BH);
aux_write_cmd(AUX_INTS_OFF); /* disable controller ints */
poll_aux_status();
- outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
- poll_aux_status();
+ ps2_outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
+ poll_aux_status();
/* reenable kbd bh */
enable_bh(KEYBOARD_BH);
+#ifndef CONFIG_SGI
free_irq(AUX_IRQ, NULL);
+#endif
MOD_DEC_USE_COUNT;
}
@@ -319,22 +404,22 @@ static int open_aux(struct inode * inode, struct file * file)
return -EBUSY;
}
queue->head = queue->tail = 0; /* Flush input queue */
+#ifndef CONFIG_SGI
if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL)) {
aux_count--;
return -EBUSY;
}
+#endif
MOD_INC_USE_COUNT;
/* disable kbd bh to avoid mixing of cmd bytes */
disable_bh(KEYBOARD_BH);
poll_aux_status();
- outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
+ ps2_outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
aux_write_dev(AUX_ENABLE_DEV); /* enable aux device */
aux_write_cmd(AUX_INTS_ON); /* enable controller ints */
poll_aux_status();
- /* reenable kbd bh */
- enable_bh(KEYBOARD_BH);
-
aux_ready = 0;
+ MOD_INC_USE_COUNT;
return 0;
}
@@ -403,7 +488,7 @@ static long write_aux(struct inode * inode, struct file * file,
char c;
if (!poll_aux_status())
break;
- outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
+ ps2_outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
if (!poll_aux_status())
break;
get_user(c, buffer++);
@@ -534,7 +619,11 @@ int psaux_init(void)
psaux_fops.release = release_qp;
} else
#endif
+#if defined(CONFIG_SGI) && defined(CONFIG_PSMOUSE)
+ if(1) {
+#else
if (aux_device_present == 0xaa) {
+#endif
printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
aux_present = 1;
kbd_read_mask = AUX_OBUF_FULL;
@@ -548,7 +637,7 @@ int psaux_init(void)
queue->proc_list = NULL;
if (!qp_found) {
#if defined INITIALIZE_DEVICE
- outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
+ ps2_outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
aux_write_ack(AUX_SET_SAMPLE);
aux_write_ack(100); /* 100 samples/sec */
aux_write_ack(AUX_SET_RES);
@@ -556,11 +645,11 @@ int psaux_init(void)
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
poll_aux_status_nosleep();
#endif /* INITIALIZE_DEVICE */
- outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
+ ps2_outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
poll_aux_status_nosleep();
- outb_p(AUX_CMD_WRITE,AUX_COMMAND);
- poll_aux_status_nosleep(); /* Disable interrupts */
- outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /* on the controller */
+ ps2_outb_p(AUX_CMD_WRITE,AUX_COMMAND);
+ poll_aux_status_nosleep(); /* Disable interrupts */
+ ps2_outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /* on the controller */
}
return 0;
}
@@ -582,9 +671,9 @@ static int poll_aux_status(void)
{
int retries=0;
- while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
- if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
- inb_p(AUX_INPUT_PORT);
+ while ((ps2_inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
+ if ((ps2_inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
+ ps2_inb_p(AUX_INPUT_PORT);
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
@@ -597,9 +686,9 @@ static int poll_aux_status_nosleep(void)
{
int retries = 0;
- while ((inb(AUX_STATUS)&0x03) && retries < 1000000) {
- if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
- inb_p(AUX_INPUT_PORT);
+ while ((ps2_inb(AUX_STATUS)&0x03) && retries < 1000000) {
+ if ((ps2_inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
+ ps2_inb_p(AUX_INPUT_PORT);
retries++;
}
return !(retries == 1000000);
diff --git a/drivers/char/selection.h b/drivers/char/selection.h
index 7054d63cd..4acbbb085 100644
--- a/drivers/char/selection.h
+++ b/drivers/char/selection.h
@@ -101,6 +101,33 @@ static inline unsigned short scr_readw(unsigned short * addr)
{
return *addr;
}
+#elif defined (CONFIG_SGI)
+#include "vt_kern.h"
+#include <linux/kd.h>
+extern void newport_blitc(unsigned short, unsigned long);
+extern void memsetw(void * s, unsigned short c, unsigned int count);
+extern void memcpyw(unsigned short *to, unsigned short *from, unsigned int count);
+extern unsigned long video_mem_term;
+
+static inline void scr_writew(unsigned short val, unsigned short * addr)
+{
+ /* always deposit the char/attr, then see if it was to "screen" mem.
+ * if so, then render the char/attr onto the real screen.
+ */
+ if(*addr != val) {
+ *addr = val;
+ if ((unsigned long)addr < video_mem_term &&
+ (unsigned long)addr >= video_mem_base &&
+ vt_cons [fg_console]->vc_mode == KD_TEXT)
+ newport_blitc(val, (unsigned long) addr);
+ }
+}
+
+static inline unsigned short scr_readw(unsigned short * addr)
+{
+ return *addr;
+}
+
#elif defined (CONFIG_VIDEO_G364) /* The G364 cards: same as above. */
extern void g364_blitc(unsigned short, unsigned long);
@@ -137,12 +164,12 @@ static inline void scr_writew(unsigned short val, unsigned short * addr)
g364_blitc(val, (unsigned long) addr); /* B&W faster */
else
g364_blitc_colour(val, (unsigned long) addr);
- }
+ }
}
static inline unsigned short scr_readw(unsigned short * addr)
{
- return *addr;
+ return *addr;
}
#else /* CONFIG_VIDEO_G364 */
@@ -151,7 +178,7 @@ static inline unsigned short scr_readw(unsigned short * addr)
*
*/
-#include <asm/io.h>
+#include <asm/io.h>
/*
* NOTE: "(long) addr < 0" tests for an Alpha kernel virtual address; this
@@ -190,6 +217,7 @@ static inline unsigned short scr_readw(unsigned short * addr)
#endif /* CONFIG_TGA_CONSOLE */
+#ifndef CONFIG_SGI
static inline void memsetw(void * s, unsigned short c, unsigned int count)
{
unsigned short * addr = (unsigned short *) s;
@@ -210,3 +238,4 @@ static inline void memcpyw(unsigned short *to, unsigned short *from,
scr_writew(scr_readw(from++), to++);
}
}
+#endif /* CONFIG_SUN_CONSOLE */
diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c
index bdac54541..d168c247a 100644
--- a/drivers/char/softdog.c
+++ b/drivers/char/softdog.c
@@ -31,7 +31,6 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
-#include <asm/system.h>
#define WATCHDOG_MINOR 130
#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
@@ -52,6 +51,7 @@ static int timer_alive = 0;
static void watchdog_fire(unsigned long data)
{
+ extern void hard_reset_now(void);
#ifdef ONLY_TESTING
printk(KERN_CRIT "SOFTDOG: Would Reboot.\n");
#else
diff --git a/drivers/char/vesa_blank.c b/drivers/char/vesa_blank.c
index 12dd71c1a..eb957180b 100644
--- a/drivers/char/vesa_blank.c
+++ b/drivers/char/vesa_blank.c
@@ -41,17 +41,6 @@
-----------------------------------------------------------------------
*/
-#include <linux/config.h>
-
-#if defined(CONFIG_ACER_PICA_61)
-#include <asm/bootinfo.h>
-/*
- * The video control ports are mapped at virtual address
- * 0xe0200000 for the onboard S3 card
- */
-#define PORT_BASE video_port_base
-unsigned long video_port_base;
-#endif
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/vga.c b/drivers/char/vga.c
index d0cd8dd9c..eaf3c9ac9 100644
--- a/drivers/char/vga.c
+++ b/drivers/char/vga.c
@@ -52,6 +52,8 @@
#ifdef __mips__
#include <asm/bootinfo.h>
+#include <asm/deskstation.h>
+#include <asm/sni.h>
/*
* The video control ports are mapped at virtual address
* 0xe0200000 for the onboard S3 card
@@ -61,7 +63,6 @@ unsigned long video_port_base;
#endif
#include <asm/io.h>
-#include <asm/slots.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -186,7 +187,7 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
&& mips_machtype == MACH_SNI_RM200_PCI)
{
can_do_color = 1;
- video_port_base = PORT_BASE_SNI;
+ video_port_base = SNI_PORT_BASE;
video_port_reg = 0x3d4;
video_port_val = 0x3d5;
video_type = VIDEO_TYPE_SNI_RM;
@@ -208,8 +209,9 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
if (mips_machgroup == MACH_GROUP_ARC
&& mips_machtype == MACH_DESKSTATION_RPC44)
{
+ /* XXX */
can_do_color = 1;
- video_port_base = PORT_BASE_RPC44;
+ video_port_base = RPC44_PORT_BASE;
video_port_reg = 0x3d4;
video_port_val = 0x3d5;
video_type = VIDEO_TYPE_VGAC;
@@ -224,26 +226,24 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
* the normal port address range.
*/
}
- /* else */ /* I specifically want to use the following code... */
-
-#define VGA_CAN_DO_64KB /* KLUDGE To get the address right below */
+ else
#endif
if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */
{
- video_mem_base = SLOTSPACE + 0xb0000;
+ video_mem_base = 0xb0000;
video_port_reg = 0x3b4;
video_port_val = 0x3b5;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
{
video_type = VIDEO_TYPE_EGAM;
- video_mem_term = SLOTSPACE + 0xb8000;
+ video_mem_term = 0xb8000;
*display_desc = "EGA+";
request_region(0x3b0,16,"ega");
}
else
{
video_type = VIDEO_TYPE_MDA;
- video_mem_term = SLOTSPACE + 0xb2000;
+ video_mem_term = 0xb2000;
*display_desc = "*MDA";
request_region(0x3b0,12,"mda");
request_region(0x3bf, 1,"mda");
@@ -252,14 +252,14 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
else /* If not, it is color. */
{
can_do_color = 1;
- video_mem_term = SLOTSPACE + 0xb8000;
+ video_mem_term = 0xb8000;
video_port_reg = 0x3d4;
video_port_val = 0x3d5;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
{
int i ;
- video_mem_term = SLOTSPACE + 0xc0000;
+ video_mem_term = 0xc0000;
if (!ORIG_VIDEO_ISVGA) {
video_type = VIDEO_TYPE_EGAC;
@@ -277,8 +277,8 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
* controllers (it seems like setting MM=01
* and COE=1 isn't necessarily a good idea)
*/
- video_mem_base = SLOTSPACE + 0xa0000;
- video_mem_term = SLOTSPACE + 0xb0000;
+ video_mem_base = 0xa0000;
+ video_mem_term = 0xb0000;
outb_p (6, 0x3ce) ;
outb_p (6, 0x3cf) ;
#endif
@@ -310,7 +310,7 @@ con_type_init(unsigned long kmem_start, const char **display_desc)
else
{
video_type = VIDEO_TYPE_CGA;
- video_mem_term = SLOTSPACE + 0xba000;
+ video_mem_term = 0xba000;
*display_desc = "*CGA";
request_region(0x3d4,2,"cga");
}
@@ -386,10 +386,10 @@ set_scrmem(int currcons, long offset)
* (sizif@botik.yaroslavl.su).
*/
-#define colourmap ((char *)(SLOTSPACE + 0xa0000))
+#define colourmap ((char *)(0xa0000))
/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
should use 0xA0000 for the bwmap as well.. */
-#define blackwmap ((char *)(SLOTSPACE + 0xa0000))
+#define blackwmap ((char *)(0xa0000))
#define cmapsz 8192
#define attrib_port (0x3c0)
#define seq_port_reg (0x3c4)
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1fc0a81b3..d5cd08183 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -187,7 +187,12 @@ _kd_mksound(unsigned int hz, unsigned int ticks)
return;
}
+#ifdef CONFIG_SGI
+void _kd_nullsound(unsigned int hz, unsigned int ticks) { }
+void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_nullsound;
+#else
void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
+#endif
/*
* We handle the console-specific ioctl's here. We allow the
diff --git a/drivers/isdn/.cvsignore b/drivers/isdn/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/isdn/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/isdn/icn/.cvsignore b/drivers/isdn/icn/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/isdn/icn/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/isdn/pcbit/.cvsignore b/drivers/isdn/pcbit/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/isdn/pcbit/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/isdn/teles/.cvsignore b/drivers/isdn/teles/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/isdn/teles/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/isdn/teles/buffers.c b/drivers/isdn/teles/buffers.c
index b01a5ab06..74510a664 100644
--- a/drivers/isdn/teles/buffers.c
+++ b/drivers/isdn/teles/buffers.c
@@ -1,6 +1,9 @@
-/* $Id: buffers.c,v 1.3 1996/05/31 00:56:53 fritz Exp $
+/* $Id: buffers.c,v 1.2 1996/07/04 22:46:20 dm Exp $
*
* $Log: buffers.c,v $
+ * Revision 1.2 1996/07/04 22:46:20 dm
+ * Merge to 2.0.1
+ *
* Revision 1.3 1996/05/31 00:56:53 fritz
* removed cli() from BufPoolAdd, since it is called
* with interrupts off anyway.
diff --git a/drivers/isdn/teles/callc.c b/drivers/isdn/teles/callc.c
index ead53cb36..90eebff21 100644
--- a/drivers/isdn/teles/callc.c
+++ b/drivers/isdn/teles/callc.c
@@ -1,6 +1,9 @@
-/* $Id: callc.c,v 1.13 1996/06/24 17:15:55 fritz Exp $
+/* $Id: callc.c,v 1.2 1996/07/04 22:46:21 dm Exp $
*
* $Log: callc.c,v $
+ * Revision 1.2 1996/07/04 22:46:21 dm
+ * Merge to 2.0.1
+ *
* Revision 1.13 1996/06/24 17:15:55 fritz
* corrected return code of teles_writebuf()
*
diff --git a/drivers/net/.cvsignore b/drivers/net/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/net/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index c674ca1a4..c1eda8235 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -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
@@ -135,6 +138,3 @@ if [ "$CONFIG_TR" = "y" ]; then
tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
fi
-if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then
- bool 'MIPS JAZZ onboard SONIC ethernet support' CONFIG_MIPS_JAZZ_SONIC
-fi
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 962542fb5..c36fd7d54 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -260,6 +260,10 @@ ifeq ($(CONFIG_SUNLANCE),y)
L_OBJS += sunlance.o
endif
+ifeq ($(CONFIG_SGISEEQ), y)
+L_OBJS += sgiseeq.o
+endif
+
ifeq ($(CONFIG_AT1700),y)
L_OBJS += at1700.o
else
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 515432696..06eb63545 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -75,6 +75,7 @@ extern int tc59x_probe(struct device *);
extern int dgrs_probe(struct device *);
extern int smc_init( struct device * );
extern int sparc_lance_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 *);
@@ -84,7 +85,6 @@ extern int hydra_probe(struct device *);
extern int atp_init(struct device *);
extern int de600_probe(struct device *);
extern int de620_probe(struct device *);
-extern int acn_net_probe(struct device *);
static int
ethif_probe(struct device *dev)
@@ -215,12 +215,12 @@ ethif_probe(struct device *dev)
#ifdef CONFIG_SUNLANCE
&& sparc_lance_probe(dev)
#endif
+#ifdef CONFIG_SGISEEQ
+ && sgiseeq_probe(dev)
+#endif
#ifdef CONFIG_MIPS_JAZZ_SONIC
&& sonic_probe(dev)
#endif
-#ifdef CONFIG_ACN_MIPS_BOARD
- && acn_net_probe(dev)
-#endif
&& 1 ) {
return 1; /* -ENODEV or -EAGAIN would be more accurate. */
}
diff --git a/drivers/net/lance32.c b/drivers/net/lance32.c
index f90e00366..d427cdbf9 100644
--- a/drivers/net/lance32.c
+++ b/drivers/net/lance32.c
@@ -36,7 +36,7 @@ static const char *version = "lance32.c:v0.10 28.4.96 tsbogend@bigbug.franken.de
#include <linux/bios32.h>
#include <asm/bitops.h>
#ifdef __mips__
-#include <asm/cache.h>
+#include <asm/pgtable.h>
#include <asm/bootinfo.h>
static unsigned long lance_base;
extern unsigned long port_base;
@@ -180,7 +180,7 @@ void lance32_probe1(struct device *dev, char *chipname, int pci_irq_line)
* have negative impact on the performance due to drivers not being
* aware of the CPU performance impact of GFP_DMA memory ...
*/
- cacheflush(lp, sizeof(*lp)+15, CF_DCACHE|CF_ALL);
+ flush_cache_all();
lp = KSEG1ADDR(lp);
lance_base = port_base;
if (mips_machgroup == MACH_GROUP_SNI_RM
@@ -567,8 +567,7 @@ lance32_start_xmit(struct sk_buff *skb, struct device *dev)
lp->tx_ring[entry].status = 0x8300;
#ifdef __mips__
- cacheflush((void *)skb->data,
- (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len, CF_DCACHE|CF_ALL);
+ flush_cache_all();
#endif
lp->cur_tx++;
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
new file mode 100644
index 000000000..3022e8a0b
--- /dev/null
+++ b/drivers/net/sgiseeq.c
@@ -0,0 +1,737 @@
+/* $Id: sgiseeq.c,v 1.17 1996/08/16 04:43:32 dm 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(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
index 000000000..023c2c065
--- /dev/null
+++ b/drivers/net/sgiseeq.h
@@ -0,0 +1,103 @@
+/* $Id: sgiseeq.h,v 1.2 1996/06/15 03:42:50 dm 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
index 75c30ca58..dfa5b272c 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -33,10 +33,10 @@ static const char *version =
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/delay.h>
-#include <asm/cache.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>
@@ -269,7 +269,7 @@ sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq)
/* now convert pointer to KSEG1 pointer */
lp->rba = (char *)KSEG1ADDR(lp->rba);
- cacheflush (lp, sizeof(*lp), CF_DCACHE|CF_ALL);
+ flush_cache_all();
dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
}
@@ -422,7 +422,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct device *dev)
lp->tx_skb[entry] = skb;
length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- cacheflush((void *)skb->data, length, CF_DCACHE|CF_ALL);
+ flush_cache_all();
/*
* Setup the transmit descriptor and issue the transmit command.
diff --git a/drivers/pci/.cvsignore b/drivers/pci/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/pci/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/sbus/.cvsignore b/drivers/sbus/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/sbus/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/sbus/char/.cvsignore b/drivers/sbus/char/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/sbus/char/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/scsi/.cvsignore b/drivers/scsi/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/scsi/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 0b5489bdf..617c80f5a 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -110,6 +110,14 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_SGIWD93),y)
+L_OBJS += sgiwd93.o wd33c93.o
+else
+ ifeq ($(CONFIG_SCSI_SGIWD93),m)
+ M_OBJS += sgiwd93.o wd33c93.o
+ endif
+endif
+
ifeq ($(CONFIG_ATARI_SCSI),y)
L_OBJS += atari_scsi.o
else
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index a77fe820f..759022208 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -165,13 +165,17 @@
#include "esp.h"
#endif
+#ifdef CONFIG_SCSI_SGIWD93
+#include "sgiwd93.h"
+#endif
+
#ifdef CONFIG_SCSI_DEBUG
#include "scsi_debug.h"
#endif
/*
-static const char RCSid[] = "$Header: /usr/src/linux-1.3.95/drivers/scsi/RCS/hosts.c,v 1.7 1996/04/25 22:21:56 root Exp root $";
+static const char RCSid[] = "$Header: /export/home0/cvs/linux/drivers/scsi/hosts.c,v 1.5 1996/08/12 11:11:54 dm Exp $";
*/
/*
@@ -303,6 +307,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_SUNESP
SCSI_SPARC_ESP,
#endif
+#ifdef CONFIG_SCSI_SGIWD93
+ SGIWD93_SCSI,
+#endif
#ifdef CONFIG_SCSI_DEBUG
SCSI_DEBUG,
#endif
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 40140e06d..ed45a57f7 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -64,7 +64,7 @@
#undef USE_STATIC_SCSI_MEMORY
/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.5 1993/09/24 12:45:18 drew Exp drew $";
+static const char RCSid[] = "$Header: /export/home0/cvs/linux/drivers/scsi/scsi.c,v 1.8 1996/08/07 02:54:28 dm Exp $";
*/
@@ -416,8 +416,12 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
/* Make sure we have something that is valid for DMA purposes */
+#ifndef CONFIG_SGI
scsi_result = ( ( !shpnt->unchecked_isa_dma )
? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA));
+#else
+ scsi_result = (scsi_init_malloc (512, GFP_DMA));
+#endif
if (scsi_result == NULL) {
printk ("Unable to obtain scsi_result buffer\n");
diff --git a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
index 044a06b39..e45d80f4e 100644
--- a/drivers/scsi/scsicam.c
+++ b/drivers/scsi/scsicam.c
@@ -22,7 +22,6 @@
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/blk.h>
-#include <asm/segment.h>
#include <asm/unaligned.h>
#include "scsi.h"
#include "hosts.h"
@@ -129,8 +128,8 @@ static int partsize(struct buffer_head *bh, unsigned long capacity,
end_head * end_sector + end_sector;
/* This is the actual _sector_ number at the end */
- logical_end = get_unaligned(&largest->start_sect) +
- get_unaligned(&largest->nr_sects);
+ logical_end = get_unaligned(&largest->start_sect)
+ + get_unaligned(&largest->nr_sects);
/* This is for >1023 cylinders */
ext_cyl= (logical_end-(end_head * end_sector + end_sector))
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 2a4062b90..c23fdb97e 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -49,7 +49,6 @@
#include <linux/module.h>
#include <asm/io.h>
-#include <asm/slot.h>
#include <asm/system.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -100,7 +99,7 @@ static int incommand; /*
in some command phase.
*/
-static unsigned int base_address = 0; /*
+static const void *base_address = NULL; /*
Where the card ROM starts,
used to calculate memory mapped
register location.
@@ -109,7 +108,7 @@ static unsigned int base_address = 0; /*
static volatile int abort_confirm = 0;
#endif
-static unsigned int st0x_cr_sr; /*
+static volatile void *st0x_cr_sr; /*
control register write,
status register read.
256 bytes in length.
@@ -120,7 +119,7 @@ static unsigned int st0x_cr_sr; /*
*/
-static unsigned int st0x_dr; /*
+static volatile void *st0x_dr; /*
data register, read write
256 bytes in length.
*/
@@ -134,31 +133,31 @@ static unsigned char controller_type = 0; /* set to SEAGATE for ST0x boards or F
static unsigned char irq = IRQ;
#define retcode(result) (((result) << 16) | (message << 8) | status)
-#define STATUS (readb(st0x_cr_sr))
+#define STATUS (*(volatile unsigned char *) st0x_cr_sr)
#define CONTROL STATUS
-#define DATA (readb(st0x_dr))
+#define DATA (*(volatile unsigned char *) st0x_dr)
void st0x_setup (char *str, int *ints) {
controller_type = SEAGATE;
- base_address = ints[1];
+ base_address = (void *) ints[1];
irq = ints[2];
}
void tmc8xx_setup (char *str, int *ints) {
controller_type = FD;
- base_address = ints[1];
+ base_address = (void *) ints[1];
irq = ints[2];
}
#ifndef OVERRIDE
-static unsigned int seagate_bases[] = {
- 0xc8000, 0xca000, 0xcc000,
- 0xce000, 0xdc000, 0xde000
+static const char * seagate_bases[] = {
+ (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
+ (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
};
typedef struct {
- const unsigned char *signature ;
+ const char *signature ;
unsigned offset;
unsigned length;
unsigned char type;
@@ -308,7 +307,7 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt)
if (!controller_type) {
#ifdef OVERRIDE
- base_address = OVERRIDE;
+ base_address = (void *) OVERRIDE;
/* CONTROLLER is used to override controller (SEAGATE or FD). PM: 07/01/93 */
#ifdef CONTROLLER
@@ -331,11 +330,12 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt)
* space for the on-board RAM instead.
*/
- for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i)
+ for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
- if (check_signature(seagate_bases[i] + signatures[j].offset,
- signatures[j].signature, signatures[j].length)) {
- base_address = seagate_bases[i];
+ if (!memcmp ((const void *) (seagate_bases[i] +
+ signatures[j].offset), (const void *) signatures[j].signature,
+ signatures[j].length)) {
+ base_address = (const void *) seagate_bases[i];
controller_type = signatures[j].type;
}
#endif /* OVERRIDE */
@@ -346,8 +346,8 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt)
if (base_address)
{
- st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00);
- st0x_dr = st0x_cr_sr + 0x200;
+ st0x_cr_sr =(void *) (((const unsigned char *) base_address) + (controller_type == SEAGATE ? 0x1a00 : 0x1c00));
+ st0x_dr = (void *) (((const unsigned char *) base_address ) + (controller_type == SEAGATE ? 0x1c00 : 0x1e00));
#ifdef DEBUG
printk("%s detected. Base address = %x, cr = %x, dr = %x\n", tpnt->name, base_address, st0x_cr_sr, st0x_dr);
#endif
@@ -364,7 +364,7 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt)
return 0;
}
instance->irq = irq;
- instance->io_port = base_address;
+ instance->io_port = (unsigned int) base_address;
#ifdef SLOW_HANDSHAKE
borken_init();
#endif
@@ -402,7 +402,7 @@ const char *seagate_st0x_info(struct Scsi_Host * shpnt) {
static char buffer[64];
sprintf(buffer, "%s at irq %d, address 0x%05X",
(controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR,
- irq, base_address);
+ irq, (unsigned int)base_address);
return buffer;
}
@@ -1091,7 +1091,6 @@ if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
SCint->transfersize, len, data);
#endif
-#warning This no longer works: rewrite in C and use readbwl/writebwl
__asm__("
cld;
"
@@ -1128,7 +1127,6 @@ if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
* We loop as long as we are in a data out phase, there is data to send,
* and BSY is still active.
*/
-#warning This no longer works: rewrite in C and use readbwl/writebwl
__asm__ (
/*
@@ -1219,7 +1217,6 @@ if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
" len = %d, data = %08x\n", hostno, SCint->underflow,
SCint->transfersize, len, data);
#endif
-#warning This no longer works: rewrite in C and use readbwl/writebwl
__asm__("
cld;
"
@@ -1268,7 +1265,6 @@ if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
* and BSY is still active
*/
-#warning This no longer works: rewrite in C and use readbwl/writebwl
__asm__ (
/*
Local variables :
@@ -1634,14 +1630,13 @@ int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
return SCSI_RESET_WAKEUP;
}
-#include <asm/uaccess.h>
+#include <asm/segment.h>
#include "sd.h"
#include <scsi/scsi_ioctl.h>
int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
- unsigned char buf[256 + sizeof (Scsi_Ioctl_Command)], cmd[6], *data, *page;
- Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
- int result, formatted_sectors, total_sectors;
+ unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page;
+ int *sizes, result, formatted_sectors, total_sectors;
int cylinders, heads, sectors;
int capacity;
@@ -1653,7 +1648,8 @@ int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
if (disk->device->scsi_level < 2)
return -1;
- data = sic->data;
+ sizes = (int *) buf;
+ data = (unsigned char *) (sizes + 2);
cmd[0] = MODE_SENSE;
cmd[1] = (disk->device->lun << 5) & 0xe5;
@@ -1667,12 +1663,12 @@ int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
* 24 bytes for each mode page.
*/
- sic->inlen = 0;
- sic->outlen = 256;
+ sizes[0] = 0;
+ sizes[1] = 256;
memcpy (data, cmd, 6);
- if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, sic))) {
+ if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
/*
* The mode page lies beyond the MODE SENSE header, with length 4, and
* the BLOCK DESCRIPTOR, with length header[3].
@@ -1685,7 +1681,7 @@ int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
cmd[2] = 0x03; /* Read page 3, format page current values */
memcpy (data, cmd, 6);
- if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, sic))) {
+ if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
page = data + 4 + data[3];
sectors = (page[10] << 8) | page[11];
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
new file mode 100644
index 000000000..83affefb6
--- /dev/null
+++ b/drivers/scsi/sgiwd93.c
@@ -0,0 +1,246 @@
+/* $Id: sgiwd93.c,v 1.7 1996/07/23 09:00:16 dm Exp $
+ * sgiwd93.c: SGI WD93 scsi driver.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * (In all truth, Jed Schimmel wrote all this code.)
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/version.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/irq.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "sgiwd93.h"
+
+#include <linux/stat.h>
+
+struct hpc_chunk {
+ struct hpc_dma_desc desc;
+ unsigned long padding;
+};
+
+struct proc_dir_entry proc_scsi_sgiwd93 = {
+ PROC_SCSI_SGIWD93, 5, "SGIWD93",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+struct Scsi_Host *sgiwd93_host = NULL;
+
+/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
+static inline void write_wd33c93_count(wd33c93_regs *regp, unsigned long value)
+{
+ regp->SASR = WD_TRANSFER_COUNT_MSB;
+ regp->SCMD = ((value >> 16) & 0xff);
+ regp->SCMD = ((value >> 8) & 0xff);
+ regp->SCMD = ((value >> 0) & 0xff);
+}
+
+static inline unsigned long read_wd33c93_count(wd33c93_regs *regp)
+{
+ unsigned long value;
+
+ regp->SASR = WD_TRANSFER_COUNT_MSB;
+ value = ((regp->SCMD & 0xff) << 16);
+ value |= ((regp->SCMD & 0xff) << 8);
+ value |= ((regp->SCMD & 0xff) << 0);
+ return value;
+}
+
+/* XXX woof! */
+static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ wd33c93_intr(sgiwd93_host);
+}
+
+#undef DEBUG_DMA
+
+static int dma_setup(Scsi_Cmnd *cmd, int datainp)
+{
+ struct WD33C93_hostdata *hdata = CMDHOSTDATA(cmd);
+ wd33c93_regs *regp = hdata->regp;
+ struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base;
+ struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer;
+
+#ifdef DEBUG_DMA
+ printk("dma_setup: datainp<%d> hcp<%p> ",
+ datainp, hcp);
+#endif
+
+ hdata->dma_dir = datainp;
+
+ if(cmd->use_sg) {
+ struct scatterlist *slp = cmd->SCp.buffer;
+ int i, totlen = 0;
+
+#ifdef DEBUG_DMA
+ printk("SCLIST<");
+#endif
+ for(i = 0; i <= (cmd->use_sg - 1); i++, hcp++) {
+#ifdef DEBUG_DMA
+ printk("[%p,%d]", slp[i].address, slp[i].length);
+#endif
+ flush_page_to_ram((unsigned long)slp[i].address);
+ hcp->desc.pbuf = PHYSADDR(slp[i].address);
+ hcp->desc.cntinfo = (slp[i].length & HPCDMA_BCNT);
+ totlen += slp[i].length;
+ }
+#ifdef DEBUG_DMA
+ printk(">tlen<%d>", totlen);
+#endif
+ hdata->dma_bounce_len = totlen; /* a trick... */
+ write_wd33c93_count(regp, totlen);
+ } else {
+ /* Non-scattered dma. */
+#ifdef DEBUG_DMA
+ printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual);
+#endif
+ flush_page_to_ram((unsigned long)cmd->SCp.ptr);
+ hcp->desc.pbuf = PHYSADDR(cmd->SCp.ptr);
+ hcp->desc.cntinfo = (cmd->SCp.this_residual & HPCDMA_BCNT);
+ hcp++;
+ write_wd33c93_count(regp, cmd->SCp.this_residual);
+ }
+
+ /* To make sure, if we trip an HPC bug, that we transfer
+ * every single byte, we tag on an extra zero length dma
+ * descriptor at the end of the chain.
+ */
+ hcp->desc.pbuf = 0;
+ hcp->desc.cntinfo = (HPCDMA_EOX);
+
+#ifdef DEBUG_DMA
+ printk(" HPCGO\n");
+#endif
+
+ /* Start up the HPC. */
+ hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer);
+ if(datainp)
+ hregs->ctrl = (HPC3_SCTRL_ACTIVE);
+ else
+ hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR);
+ return 0;
+}
+
+static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
+ int status)
+{
+ struct WD33C93_hostdata *hdata = INSTHOSTDATA(instance);
+ wd33c93_regs *regp = hdata->regp;
+ struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) SCpnt->host->base;
+
+#ifdef DEBUG_DMA
+ printk("dma_stop: status<%d> ", status);
+#endif
+
+ /* First stop the HPC and flush it's FIFO. */
+ if(hdata->dma_dir) {
+ hregs->ctrl |= HPC3_SCTRL_FLUSH;
+ while(hregs->ctrl & HPC3_SCTRL_ACTIVE)
+ barrier();
+ }
+ hregs->ctrl = 0;
+
+ /* See how far we got and update scatterlist state if necessary. */
+ if(SCpnt->use_sg) {
+ struct scatterlist *slp = SCpnt->SCp.buffer;
+ int totlen, wd93_residual, transferred, i;
+
+ /* Yep, we were doing the scatterlist thang. */
+ totlen = hdata->dma_bounce_len;
+ wd93_residual = read_wd33c93_count(regp);
+ transferred = totlen - wd93_residual;
+
+#ifdef DEBUG_DMA
+ printk("tlen<%d>resid<%d>transf<%d> ",
+ totlen, wd93_residual, transferred);
+#endif
+
+ /* Avoid long winded partial-transfer search for common case. */
+ if(transferred != totlen) {
+ /* This is the nut case. */
+#ifdef DEBUG_DMA
+ printk("Jed was here...");
+#endif
+ for(i = 0; i <= (SCpnt->use_sg - 1); i++) {
+ if(slp[i].length >= transferred)
+ break;
+ transferred -= slp[i].length;
+ }
+ } else {
+ /* This is the common case. */
+#ifdef DEBUG_DMA
+ printk("did it all...");
+#endif
+ i = (SCpnt->use_sg - 1);
+ }
+ SCpnt->SCp.buffer = &slp[i];
+ SCpnt->SCp.buffers_residual = (SCpnt->use_sg - 1 - i);
+ SCpnt->SCp.ptr = (char *) slp[i].address;
+ SCpnt->SCp.this_residual = slp[i].length;
+ }
+#ifdef DEBUG_DMA
+ printk("\n");
+#endif
+}
+
+static inline void init_hpc_chain(uchar *buf)
+{
+ struct hpc_chunk *hcp = (struct hpc_chunk *) buf;
+ unsigned long start, end;
+
+ start = (unsigned long) buf;
+ end = start + PAGE_SIZE;
+ while(start < end) {
+ hcp->desc.pnext = PHYSADDR((hcp + 1));
+ hcp->desc.cntinfo = HPCDMA_EOX;
+ hcp++;
+ start += sizeof(struct hpc_chunk);
+ };
+ hcp--;
+ hcp->desc.pnext = PHYSADDR(buf);
+}
+
+int sgiwd93_detect(Scsi_Host_Template *HPsUX)
+{
+ static unsigned char called = 0;
+ struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0;
+ struct WD33C93_hostdata *hdata;
+ uchar *buf;
+
+ if(called)
+ return 0; /* Should bitch on the console about this... */
+
+ HPsUX->proc_dir = &proc_scsi_sgiwd93;
+
+ sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
+ sgiwd93_host->base = (unsigned char *) hregs;
+
+ buf = (uchar *) get_free_page(GFP_KERNEL);
+ init_hpc_chain(buf);
+ flush_page_to_ram((unsigned long) buf);
+
+ wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003,
+ dma_setup, dma_stop, WD33C93_FS_16_20);
+
+ hdata = INSTHOSTDATA(sgiwd93_host);
+ hdata->no_sync = 0;
+ hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
+ flush_page_to_ram((unsigned long) buf);
+
+ request_irq(1, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host);
+ called = 1;
+
+ return 1; /* Found one. */
+}
diff --git a/drivers/scsi/sgiwd93.h b/drivers/scsi/sgiwd93.h
new file mode 100644
index 000000000..83b5a29c6
--- /dev/null
+++ b/drivers/scsi/sgiwd93.h
@@ -0,0 +1,52 @@
+/* $Id: sgiwd93.h,v 1.4 1996/07/14 06:43:13 dm Exp $
+ * sgiwd93.h: SGI WD93 scsi definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _SGIWD93_H
+#define _SGIWD93_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 8
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+int sgiwd93_detect(Scsi_Host_Template *);
+const char *wd33c93_info(void);
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+
+extern struct proc_dir_entry proc_scsi_sgiwd93;
+
+#define SGIWD93_SCSI {/* next */ NULL, \
+ /* usage_count */ NULL, \
+ /* proc_dir_entry */ &proc_scsi_sgiwd93, \
+ /* proc_info */ NULL, \
+ /* name */ "SGI WD93", \
+ /* detect */ sgiwd93_detect, \
+ /* release */ NULL, \
+ /* info */ NULL, \
+ /* command */ NULL, \
+ /* queuecommand */ wd33c93_queuecommand, \
+ /* abort */ wd33c93_abort, \
+ /* reset */ wd33c93_reset, \
+ /* slave_attach */ NULL, \
+ /* bios_param */ NULL, \
+ /* can_queue */ CAN_QUEUE, \
+ /* this_id */ 7, \
+ /* sg_tablesize */ SG_ALL, \
+ /* cmd_per_lun */ CMD_PER_LUN, \
+ /* present */ 0, \
+ /* unchecked_isa_dma */ 0, \
+ /* use_clustering */ DISABLE_CLUSTERING \
+}
+
+#endif /* !(_SGIWD93_H) */
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index fa43592c8..67cbdcf7e 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -55,20 +55,18 @@
* almost as fast while being much easier to define, track,
* and debug.
*
- *
* TODO:
* more speed. linked commands.
*
- *
* People with bug reports, wish-lists, complaints, comments,
* or improvements are asked to pah-leeez email me (John Shifflett)
* at john@geolog.com or jshiffle@netcom.com! I'm anxious to get
* this thing into as good a shape as possible, and I'm positive
* there are lots of lurking bugs and "Stupid Places".
- *
*/
#include <asm/system.h>
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/delay.h>
@@ -93,26 +91,24 @@
*/
/*#define PROC_INTERFACE*/ /* add code for /proc/scsi/wd33c93/xxx interface */
-#define SYNC_DEBUG /* extra info on sync negotiation printed */
-#define DEBUGGING_ON /* enable command-line debugging bitmask */
-#define DEBUG_DEFAULTS 0 /* default debugging bitmask */
+#undef SYNC_DEBUG /* extra info on sync negotiation printed */
+#define DEBUGGING_ON /* enable command-line debugging bitmask */
+#define DEBUG_DEFAULTS 0x00 /* default debugging bitmask */
#define WD33C93_VERSION "1.21"
#define WD33C93_DATE "20/Apr/1996"
#ifdef DEBUGGING_ON
-#define DB(f,a) if (hostdata->args & (f)) a;
+#define DB(f,a) if (hostdata->args & (f)) (a)
#else
#define DB(f,a)
#endif
-#define IS_DIR_OUT(cmd) ((cmd)->cmnd[0] == WRITE_6 || \
- (cmd)->cmnd[0] == WRITE_10 || \
- (cmd)->cmnd[0] == WRITE_12)
+#define IS_DIR_OUT(cmd) (((cmd)->cmnd[0] == WRITE_6) || \
+ ((cmd)->cmnd[0] == WRITE_10) || \
+ ((cmd)->cmnd[0] == WRITE_12))
-
-/*
- * setup_strings is an array of strings that define some of the operating
+/* setup_strings is an array of strings that define some of the operating
* parameters and settings for this driver. It is used unless an amiboot
* or insmod command line has been specified, in which case those settings
* are combined with the ones here. The driver recognizes the following
@@ -166,1341 +162,1250 @@ unsigned long disc_allowed_total;
unsigned long disc_taken_total;
#endif
-
-inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
+static inline uchar read_wd33c93(wd33c93_regs *regp, uchar reg_num)
{
- regp->SASR = reg_num;
- return(regp->SCMD);
+ regp->SASR = reg_num;
+ return regp->SCMD;
}
-
#define READ_AUX_STAT() (regp->SASR)
-
-inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
+static inline void write_wd33c93(wd33c93_regs *regp, uchar reg_num, uchar value)
{
- regp->SASR = reg_num;
- regp->SCMD = value;
+ regp->SASR = reg_num;
+ regp->SCMD = value;
}
-
-inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
+static inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
{
- regp->SASR = WD_COMMAND;
- regp->SCMD = cmd;
+ regp->SASR = WD_COMMAND;
+ regp->SCMD = cmd;
}
-
-inline uchar read_1_byte(wd33c93_regs *regp)
+static inline uchar read_1_byte(wd33c93_regs *regp)
{
-uchar asr;
-uchar x = 0;
-
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
- write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO|0x80);
- do {
- asr = READ_AUX_STAT();
- if (asr & ASR_DBR)
- x = read_wd33c93(regp, WD_DATA);
- } while (!(asr & ASR_INT));
- return x;
+ uchar asr;
+ uchar x = 0;
+
+ write_wd33c93(regp, WD_CONTROL, (CTRL_IDI | CTRL_EDI | CTRL_POLLED));
+ write_wd33c93_cmd(regp, (WD_CMD_TRANS_INFO | 0x80));
+ do {
+ asr = READ_AUX_STAT();
+ if (asr & ASR_DBR)
+ x = read_wd33c93(regp, WD_DATA);
+ } while (!(asr & ASR_INT));
+ return x;
}
-
-void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
+static inline void write_wd33c93_count(wd33c93_regs *regp, unsigned long value)
{
- regp->SASR = WD_TRANSFER_COUNT_MSB;
- regp->SCMD = value >> 16;
- regp->SCMD = value >> 8;
- regp->SCMD = value;
+ regp->SASR = WD_TRANSFER_COUNT_MSB;
+ regp->SCMD = ((value >> 16) & 0xff);
+ regp->SCMD = ((value >> 8) & 0xff);
+ regp->SCMD = ((value >> 0) & 0xff);
}
-
-unsigned long read_wd33c93_count(wd33c93_regs *regp)
+static inline unsigned long read_wd33c93_count(wd33c93_regs *regp)
{
-unsigned long value;
+ unsigned long value;
- regp->SASR = WD_TRANSFER_COUNT_MSB;
- value = regp->SCMD << 16;
- value |= regp->SCMD << 8;
- value |= regp->SCMD;
- return value;
+ regp->SASR = WD_TRANSFER_COUNT_MSB;
+ value = ((regp->SCMD & 0xff) << 16);
+ value |= ((regp->SCMD & 0xff) << 8);
+ value |= ((regp->SCMD & 0xff) << 0);
+ return value;
}
-
-
static struct sx_period sx_table[] = {
- { 1, 0x20},
- {252, 0x20},
- {376, 0x30},
- {500, 0x40},
- {624, 0x50},
- {752, 0x60},
- {876, 0x70},
- {1000,0x00},
- {0, 0} };
-
-int round_period(unsigned int period)
+ { 1, 0x20},
+ {252, 0x20},
+ {376, 0x30},
+ {500, 0x40},
+ {624, 0x50},
+ {752, 0x60},
+ {876, 0x70},
+ {1000,0x00},
+ {0, 0}
+};
+
+static inline int round_period(unsigned int period)
{
-int x;
-
- for (x=1; sx_table[x].period_ns; x++) {
- if ((period <= sx_table[x-0].period_ns) &&
- (period > sx_table[x-1].period_ns)) {
- return x;
- }
- }
- return 7;
+ int x;
+
+ for (x = 1; sx_table[x].period_ns; x++) {
+ if ((period <= sx_table[x-0].period_ns) &&
+ (period > sx_table[x-1].period_ns)) {
+ return x;
+ }
+ }
+ return 7;
}
-uchar calc_sync_xfer(unsigned int period, unsigned int offset)
+static inline uchar calc_sync_xfer(unsigned int period, unsigned int offset)
{
-uchar result;
+ uchar result;
- period *= 4; /* convert SDTR code to ns */
- result = sx_table[round_period(period)].reg_value;
- result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF;
- return result;
+ /* convert SDTR code to ns */
+ period *= 4;
+ result = sx_table[round_period(period)].reg_value;
+ result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
+ return result;
}
-
-
void wd33c93_execute(struct Scsi_Host *instance);
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
-struct WD33C93_hostdata *hostdata;
-Scsi_Cmnd *tmp;
-unsigned long flags;
-
-
- save_flags(flags);
- cli();
- hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
-
-DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
-
-/* Set up a few fields in the Scsi_Cmnd structure for our own use:
- * - host_scribble is the pointer to the next cmd in the input queue
- * - scsi_done points to the routine we call when a cmd is finished
- * - result is what you'd expect
- */
-
- cmd->host_scribble = NULL;
- cmd->scsi_done = done;
- cmd->result = 0;
-
-/* We use the Scsi_Pointer structure that's included with each command
- * as a scratchpad (as it's intended to be used!). The handy thing about
- * the SCp.xxx fields is that they're always associated with a given
- * cmd, and are preserved across disconnect-reselect. This means we
- * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages
- * if we keep all the critical pointers and counters in SCp:
- * - SCp.ptr is the pointer into the RAM buffer
- * - SCp.this_residual is the size of that buffer
- * - SCp.buffer points to the current scatter-gather buffer
- * - SCp.buffers_residual tells us how many S.G. buffers there are
- * - SCp.have_data_in is not used
- * - SCp.sent_command is not used
- * - SCp.phase records this command's SRCID_ER bit setting
- */
-
- if (cmd->use_sg) {
- cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
- cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
- cmd->SCp.this_residual = cmd->SCp.buffer->length;
- }
- else {
- cmd->SCp.buffer = NULL;
- cmd->SCp.buffers_residual = 0;
- cmd->SCp.ptr = (char *)cmd->request_buffer;
- cmd->SCp.this_residual = cmd->request_bufflen;
- }
-
-/* Preset the command status to GOOD, since that's the normal case */
-
- cmd->SCp.Status = GOOD;
-
- /*
- * Add the cmd to the end of 'input_Q'. Note that REQUEST SENSE
- * commands are added to the head of the queue so that the desired
- * sense data is not lost before REQUEST_SENSE executes.
- */
-
- if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
- cmd->host_scribble = (uchar *)hostdata->input_Q;
- hostdata->input_Q = cmd;
- }
- else { /* find the end of the queue */
- for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble;
- tmp=(Scsi_Cmnd *)tmp->host_scribble)
- ;
- tmp->host_scribble = (uchar *)cmd;
- }
-
-/* We know that there's at least one command in 'input_Q' now.
- * Go see if any of them are runnable!
- */
-
- wd33c93_execute(cmd->host);
-
-DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
-
- restore_flags(flags);
- return 0;
+ struct WD33C93_hostdata *hostdata = CMDHOSTDATA(cmd);
+ Scsi_Cmnd *tmp;
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ DB(DB_QCMD,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid));
+
+ /* Set up a few fields in the Scsi_Cmnd structure for our own use:
+ * - host_scribble is the pointer to the next cmd in the input queue
+ * - scsi_done points to the routine we call when a cmd is finished
+ * - result is what you'd expect
+ */
+ cmd->host_scribble = NULL;
+ cmd->scsi_done = done;
+ cmd->result = 0;
+
+ /* We use the Scsi_Pointer structure that's included with each command
+ * as a scratchpad (as it's intended to be used!). The handy thing about
+ * the SCp.xxx fields is that they're always associated with a given
+ * cmd, and are preserved across disconnect-reselect. This means we
+ * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages
+ * if we keep all the critical pointers and counters in SCp:
+ * - SCp.ptr is the pointer into the RAM buffer
+ * - SCp.this_residual is the size of that buffer
+ * - SCp.buffer points to the current scatter-gather buffer
+ * - SCp.buffers_residual tells us how many S.G. buffers there are
+ * - SCp.have_data_in is not used
+ * - SCp.sent_command is not used
+ * - SCp.phase records this command's SRCID_ER bit setting
+ */
+ if (cmd->use_sg) {
+ cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+ cmd->SCp.buffers_residual = cmd->use_sg - 1;
+ cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;
+ cmd->SCp.this_residual = cmd->SCp.buffer->length;
+ } else {
+ cmd->SCp.buffer = NULL;
+ cmd->SCp.buffers_residual = 0;
+ cmd->SCp.ptr = (char *) cmd->request_buffer;
+ cmd->SCp.this_residual = cmd->request_bufflen;
+ }
+
+ /* Preset the command status to GOOD, since that's the normal case */
+ cmd->SCp.Status = GOOD;
+
+ /* Add the cmd to the end of 'input_Q'. Note that REQUEST SENSE
+ * commands are added to the head of the queue so that the desired
+ * sense data is not lost before REQUEST_SENSE executes.
+ */
+ if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+ cmd->host_scribble = (uchar *) hostdata->input_Q;
+ hostdata->input_Q = cmd;
+ } else {
+ /* find the end of the queue */
+ for (tmp = (Scsi_Cmnd *) hostdata->input_Q;
+ tmp->host_scribble;
+ tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ ;
+ tmp->host_scribble = (uchar *) cmd;
+ }
+
+ /* We know that there's at least one command in 'input_Q' now.
+ * Go see if any of them are runnable!
+ */
+ wd33c93_execute(cmd->host);
+
+ DB(DB_QCMD,printk(")Q-%ld ",cmd->pid));
+ restore_flags(flags);
+ return 0;
}
-
-
-/*
- * This routine attempts to start a scsi command. If the host_card is
+/* This routine attempts to start a scsi command. If the host_card is
* already connected, we give up immediately. Otherwise, look through
* the input_Q, using the first command we find that's intended
* for a currently non-busy target/lun.
*/
-void wd33c93_execute (struct Scsi_Host *instance)
+void wd33c93_execute(struct Scsi_Host *instance)
{
-struct WD33C93_hostdata *hostdata;
-wd33c93_regs *regp;
-Scsi_Cmnd *cmd, *prev;
-unsigned long flags;
-int i;
-
-
- save_flags(flags);
- cli();
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
- regp = hostdata->regp;
-
-DB(DB_EXECUTE,printk("EX("))
-
- if (hostdata->selecting || hostdata->connected) {
-
-DB(DB_EXECUTE,printk(")EX-0 "))
-
- restore_flags(flags);
- return;
- }
-
- /*
- * Search through the input_Q for a command destined
- * for an idle target/lun.
- */
-
- cmd = (Scsi_Cmnd *)hostdata->input_Q;
- prev = 0;
- while (cmd) {
- if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
- break;
- prev = cmd;
- cmd = (Scsi_Cmnd *)cmd->host_scribble;
- }
-
- /* quit if queue empty or all possible targets are busy */
-
- if (!cmd) {
-
-DB(DB_EXECUTE,printk(")EX-1 "))
-
- restore_flags(flags);
- return;
- }
-
- /* remove command from queue */
-
- if (prev)
- prev->host_scribble = cmd->host_scribble;
- else
- hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
-
- /*
- * Start the selection process
- */
-
- if (IS_DIR_OUT(cmd))
- write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
- else
- write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
-
-/* Now we need to figure out whether or not this command is a good
- * candidate for disconnect/reselect. We guess to the best of our
- * ability, based on a set of hierarchical rules. When several
- * devices are operating simultaneously, disconnects are usually
- * an advantage. In a single device system, or if only 1 device
- * is being accessed, transfers usually go faster if disconnects
- * are not allowed:
- *
- * + Commands should NEVER disconnect if hostdata->disconnect =
- * DIS_NEVER (this holds for tape drives also), and ALWAYS
- * disconnect if hostdata->disconnect = DIS_ALWAYS.
- * + Tape drive commands should always be allowed to disconnect.
- * + Disconnect should be allowed if disconnected_Q isn't empty.
- * + Commands should NOT disconnect if input_Q is empty.
- * + Disconnect should be allowed if there are commands in input_Q
- * for a different target/lun. In this case, the other commands
- * should be made disconnect-able, if not already.
- *
- * I know, I know - this code would flunk me out of any
- * "C Programming 101" class ever offered. But it's easy
- * to change around and experiment with for now.
- */
-
- cmd->SCp.phase = 0; /* assume no disconnect */
- if (hostdata->disconnect == DIS_NEVER)
- goto no;
- if (hostdata->disconnect == DIS_ALWAYS)
- goto yes;
- if (cmd->device->type == 1) /* tape drive? */
- goto yes;
- if (hostdata->disconnected_Q) /* other commands disconnected? */
- goto yes;
- if (!(hostdata->input_Q)) /* input_Q empty? */
- goto no;
- for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
- prev=(Scsi_Cmnd *)prev->host_scribble) {
- if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) {
- for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
- prev=(Scsi_Cmnd *)prev->host_scribble)
- prev->SCp.phase = 1;
- goto yes;
- }
- }
- goto no;
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ wd33c93_regs *regp = hostdata->regp;
+ Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->input_Q;
+ Scsi_Cmnd *prev = 0;
+ unsigned long flags;
+ int i;
+
+ save_flags(flags); cli();
+ DB(DB_EXECUTE, printk("EX("));
+
+ if (hostdata->selecting || hostdata->connected) {
+ DB(DB_EXECUTE, printk(")EX-0 "));
+ goto execute_out;
+ }
+
+ /* Search through the input_Q for a command destined
+ * for an idle target/lun.
+ */
+ while (cmd) {
+ if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
+ break;
+ prev = cmd;
+ cmd = (Scsi_Cmnd *) cmd->host_scribble;
+ }
+
+ /* Quit if queue empty or all possible targets are busy. */
+ if (!cmd) {
+ DB(DB_EXECUTE, printk(")EX-1 "));
+ goto execute_out;
+ }
+
+ /* Remove command from queue. */
+ if (prev)
+ prev->host_scribble = cmd->host_scribble;
+ else
+ hostdata->input_Q = (Scsi_Cmnd *) cmd->host_scribble;
+
+ /* Start the selection process. */
+ if (IS_DIR_OUT(cmd))
+ write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
+ else
+ write_wd33c93(regp, WD_DESTINATION_ID, (cmd->target | DSTID_DPD));
+
+ /* Now we need to figure out whether or not this command is a good
+ * candidate for disconnect/reselect. We guess to the best of our
+ * ability, based on a set of hierarchical rules. When several
+ * devices are operating simultaneously, disconnects are usually
+ * an advantage. In a single device system, or if only 1 device
+ * is being accessed, transfers usually go faster if disconnects
+ * are not allowed:
+ *
+ * + Commands should NEVER disconnect if hostdata->disconnect =
+ * DIS_NEVER (this holds for tape drives also), and ALWAYS
+ * disconnect if hostdata->disconnect = DIS_ALWAYS.
+ * + Tape drive commands should always be allowed to disconnect.
+ * + Disconnect should be allowed if disconnected_Q isn't empty.
+ * + Commands should NOT disconnect if input_Q is empty.
+ * + Disconnect should be allowed if there are commands in input_Q
+ * for a different target/lun. In this case, the other commands
+ * should be made disconnect-able, if not already.
+ *
+ * I know, I know - this code would flunk me out of any
+ * "C Programming 101" class ever offered. But it's easy
+ * to change around and experiment with for now.
+ */
+ cmd->SCp.phase = 0; /* assume no disconnect */
+ if (hostdata->disconnect == DIS_NEVER)
+ goto no;
+ if ((hostdata->disconnect == DIS_ALWAYS) || (cmd->device->type == 1) ||
+ (hostdata->disconnected_Q))
+ goto yes;
+ if (!(hostdata->input_Q)) /* input_Q empty? */
+ goto no;
+ for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
+ prev=(Scsi_Cmnd *)prev->host_scribble) {
+ if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) {
+ for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
+ prev=(Scsi_Cmnd *)prev->host_scribble)
+ prev->SCp.phase = 1;
+ goto yes;
+ }
+ }
+ goto no;
yes:
- cmd->SCp.phase = 1;
+ cmd->SCp.phase = 1;
#ifdef PROC_INTERFACE
- disc_allowed_total++;
+ disc_allowed_total++;
#endif
no:
- write_wd33c93(regp, WD_SOURCE_ID, ((cmd->SCp.phase)?SRCID_ER:0));
-
- write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
- write_wd33c93(regp,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
- hostdata->busy[cmd->target] |= (1 << cmd->lun);
-
- if ((hostdata->level2 == L2_NONE) ||
- (hostdata->sync_stat[cmd->target] == SS_UNSET)) {
-
- /*
- * Do a 'Select-With-ATN' command. This will end with
- * one of the following interrupts:
- * CSR_RESEL_AM: failure - can try again later.
- * CSR_TIMEOUT: failure - give up.
- * CSR_SELECT: success - proceed.
- */
-
- hostdata->selecting = cmd;
-
-/* Every target has its own synchronous transfer setting, kept in the
- * sync_xfer array, and a corresponding status byte in sync_stat[].
- * Each target's sync_stat[] entry is initialized to SX_UNSET, and its
- * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
- * means that the parameters are undetermined as yet, and that we
- * need to send an SDTR message to this device after selection is
- * complete. We set SS_FIRST to tell the interrupt routine to do so,
- * unless we've been asked not to try synchronous transfers on this
- * target (and _all_ luns within it): In this case we set SS_SET to
- * make the defaults final.
- */
- if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
- if (hostdata->no_sync & (1 << cmd->target))
- hostdata->sync_stat[cmd->target] = SS_SET;
- else
- hostdata->sync_stat[cmd->target] = SS_FIRST;
- }
- hostdata->state = S_SELECTING;
- write_wd33c93_count(regp,0); /* guarantee a DATA_PHASE interrupt */
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
- }
-
- else {
-
- /*
- * Do a 'Select-With-ATN-Xfer' command. This will end with
- * one of the following interrupts:
- * CSR_RESEL_AM: failure - can try again later.
- * CSR_TIMEOUT: failure - give up.
- * anything else: success - proceed.
- */
-
- hostdata->connected = cmd;
- write_wd33c93(regp, WD_COMMAND_PHASE, 0);
-
- /* copy command_descriptor_block into WD chip
- * (take advantage of auto-incrementing)
- */
-
- regp->SASR = WD_CDB_1;
- for (i=0; i<cmd->cmd_len; i++)
- regp->SCMD = cmd->cmnd[i];
-
- /* The wd33c93 only knows about Group 0, 1, and 5 commands when
- * it's doing a 'select-and-transfer'. To be safe, we write the
- * size of the CDB into the OWN_ID register for every case. This
- * way there won't be problems with vendor-unique, audio, etc.
- */
-
- write_wd33c93(regp, WD_OWN_ID, cmd->cmd_len);
-
- /* When doing a non-disconnect command, we can save ourselves a DATA
- * phase interrupt later by setting everything up now.
- */
-
- if (cmd->SCp.phase == 0) {
- if (hostdata->dma_setup(cmd,
- (IS_DIR_OUT(cmd))?DATA_OUT_DIR:DATA_IN_DIR))
- write_wd33c93_count(regp,0); /* guarantee a DATA_PHASE interrupt */
- else {
- write_wd33c93_count(regp, cmd->SCp.this_residual);
- write_wd33c93(regp,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
- hostdata->dma = D_DMA_RUNNING;
- }
- }
- else
- write_wd33c93_count(regp,0); /* guarantee a DATA_PHASE interrupt */
-
- hostdata->state = S_RUNNING_LEVEL2;
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- }
-
- /*
- * Since the SCSI bus can handle only 1 connection at a time,
- * we get out of here now. If the selection fails, or when
- * the command disconnects, we'll come back to this routine
- * to search the input_Q again...
- */
-
-DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
-
- restore_flags(flags);
+ write_wd33c93(regp, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0));
+ write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
+ write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
+ hostdata->sync_xfer[cmd->target]);
+
+ hostdata->busy[cmd->target] |= (1 << cmd->lun);
+ if ((hostdata->level2 == L2_NONE) ||
+ (hostdata->sync_stat[cmd->target] == SS_UNSET)) {
+ /* Do a 'Select-With-ATN' command. This will end with
+ * one of the following interrupts:
+ * CSR_RESEL_AM: failure - can try again later.
+ * CSR_TIMEOUT: failure - give up.
+ * CSR_SELECT: success - proceed.
+ */
+ hostdata->selecting = cmd;
+
+ /* Every target has its own synchronous transfer
+ * setting, kept in the sync_xfer array, and a
+ * corresponding status byte in sync_stat[]. Each
+ * target's sync_stat[] entry is initialized to
+ * SX_UNSET, and its sync_xfer[] entry is initialized
+ * to the default/safe value. SS_UNSET means that the
+ * parameters are undetermined as yet, and that we
+ * need to send an SDTR message to this device after
+ * selection is complete. We set SS_FIRST to tell the
+ * interrupt routine to do so, unless we've been asked
+ * not to try synchronous transfers on this target
+ * (and _all_ luns within it): In this case we set
+ * SS_SET to make the defaults final.
+ */
+ if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
+ if (hostdata->no_sync & (1 << cmd->target))
+ hostdata->sync_stat[cmd->target] = SS_SET;
+ else
+ hostdata->sync_stat[cmd->target] = SS_FIRST;
+ }
+ hostdata->state = S_SELECTING;
+
+ /* guarantee a DATA_PHASE interrupt */
+ write_wd33c93_count(regp, 0);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
+ } else {
+ /* Do a 'Select-With-ATN-Xfer' command. This will end with
+ * one of the following interrupts:
+ * CSR_RESEL_AM: failure - can try again later.
+ * CSR_TIMEOUT: failure - give up.
+ * anything else: success - proceed.
+ */
+ hostdata->connected = cmd;
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0);
+
+ /* copy command_descriptor_block into WD chip
+ * (take advantage of auto-incrementing)
+ */
+ regp->SASR = WD_CDB_1;
+ for (i = 0; i < cmd->cmd_len; i++)
+ regp->SCMD = cmd->cmnd[i];
+
+ /* The wd33c93 only knows about Group 0, 1, and 5 commands when
+ * it's doing a 'select-and-transfer'. To be safe, we write the
+ * size of the CDB into the OWN_ID register for every case. This
+ * way there won't be problems with vendor-unique, audio, etc.
+ */
+ write_wd33c93(regp, WD_OWN_ID, cmd->cmd_len);
+
+ /* When doing a non-disconnect command, we can save ourselves
+ * a DATA phase interrupt later by setting everything up now.
+ */
+ if (cmd->SCp.phase == 0) {
+ if (hostdata->dma_setup(cmd, (IS_DIR_OUT(cmd)) ?
+ DATA_OUT_DIR : DATA_IN_DIR)) {
+ /* guarantee a DATA_PHASE interrupt */
+ write_wd33c93_count(regp, 0);
+ } else {
+ /* write_wd33c93_count(regp, cmd->SCp.this_residual); */
+ write_wd33c93(regp, WD_CONTROL,
+ (CTRL_IDI | CTRL_EDI | CTRL_DMA));
+ hostdata->dma = D_DMA_RUNNING;
+ }
+ } else {
+ /* guarantee a DATA_PHASE interrupt */
+ write_wd33c93_count(regp, 0);
+ }
+
+ hostdata->state = S_RUNNING_LEVEL2;
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ }
+
+ /* Since the SCSI bus can handle only 1 connection at a time,
+ * we get out of here now. If the selection fails, or when
+ * the command disconnects, we'll come back to this routine
+ * to search the input_Q again...
+ */
+ DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:":"", cmd->pid));
+execute_out:
+ restore_flags(flags);
}
-
-
void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
int data_in_dir, struct WD33C93_hostdata *hostdata)
{
-uchar asr;
-
-DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out"))
-
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
- write_wd33c93_count(regp,cnt);
- write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
- if (data_in_dir) {
- do {
- asr = READ_AUX_STAT();
- if (asr & ASR_DBR)
- *buf++ = read_wd33c93(regp, WD_DATA);
- } while (!(asr & ASR_INT));
- }
- else {
- do {
- asr = READ_AUX_STAT();
- if (asr & ASR_DBR)
- write_wd33c93(regp, WD_DATA, *buf++);
- } while (!(asr & ASR_INT));
- }
-
- /* Note: we are returning with the interrupt UN-cleared.
- * Since (presumably) an entire I/O operation has
- * completed, the bus phase is probably different, and
- * the interrupt routine will discover this when it
- * responds to the uncleared int.
- */
-
+ uchar asr;
+
+ DB(DB_TRANS,printk("(%p,%d,%s)", buf, cnt, (data_in_dir ? "in" : "out")));
+ write_wd33c93(regp, WD_CONTROL, (CTRL_IDI | CTRL_EDI | CTRL_POLLED));
+ write_wd33c93_count(regp, cnt);
+ write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
+ if (data_in_dir) {
+ do {
+ asr = READ_AUX_STAT();
+ if (asr & ASR_DBR)
+ *buf++ = read_wd33c93(regp, WD_DATA);
+ } while (!(asr & ASR_INT));
+ } else {
+ do {
+ asr = READ_AUX_STAT();
+ if (asr & ASR_DBR)
+ write_wd33c93(regp, WD_DATA, *buf++);
+ } while (!(asr & ASR_INT));
+ }
+ /* Note: we are returning with the interrupt UN-cleared.
+ * Since (presumably) an entire I/O operation has
+ * completed, the bus phase is probably different, and
+ * the interrupt routine will discover this when it
+ * responds to the uncleared int.
+ */
}
-
-
void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
{
-struct WD33C93_hostdata *hostdata;
-
- hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
-
-/* Normally, you'd expect 'this_residual' to be non-zero here.
- * In a series of scatter-gather transfers, however, this
- * routine will usually be called with 'this_residual' equal
- * to 0 and 'buffers_residual' non-zero. This means that a
- * previous transfer completed, clearing 'this_residual', and
- * now we need to setup the next scatter-gather buffer as the
- * source or destination for THIS transfer.
- */
- if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
- ++cmd->SCp.buffer;
- --cmd->SCp.buffers_residual;
- cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = cmd->SCp.buffer->address;
- }
-
- write_wd33c93(regp,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
-
-/* 'dma_setup()' will return TRUE if we can't do DMA. */
-
- if (hostdata->dma_setup(cmd, data_in_dir)) {
- transfer_pio(regp, (uchar *)&cmd->SCp.ptr, cmd->SCp.this_residual,
- data_in_dir, hostdata);
- }
-
-/* We are able to do DMA (in fact, the Amiga hardware is
- * already going!), so start up the wd33c93 in DMA mode.
- * We set 'hostdata->dma' = D_DMA_RUNNING so that when the
- * transfer completes and causes an interrupt, we're
- * reminded to tell the Amiga to shut down its end. We'll
- * postpone the updating of 'this_residual' and 'ptr'
- * until then.
- */
-
- else {
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
- write_wd33c93_count(regp,cmd->SCp.this_residual);
-
- if ((hostdata->level2 >= L2_DATA) || (cmd->SCp.phase == 0)) {
- write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- hostdata->state = S_RUNNING_LEVEL2;
- }
- else
- write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
-
- hostdata->dma = D_DMA_RUNNING;
- }
+ struct WD33C93_hostdata *hostdata = CMDHOSTDATA(cmd);
+
+ /* Normally, you'd expect 'this_residual' to be non-zero here.
+ * In a series of scatter-gather transfers, however, this
+ * routine will usually be called with 'this_residual' equal
+ * to 0 and 'buffers_residual' non-zero. This means that a
+ * previous transfer completed, clearing 'this_residual', and
+ * now we need to setup the next scatter-gather buffer as the
+ * source or destination for THIS transfer.
+ */
+ if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+ ++cmd->SCp.buffer;
+ --cmd->SCp.buffers_residual;
+ cmd->SCp.this_residual = cmd->SCp.buffer->length;
+ cmd->SCp.ptr = cmd->SCp.buffer->address;
+ }
+
+ write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
+ hostdata->sync_xfer[cmd->target]);
+
+ /* 'dma_setup()' will return TRUE if we can't do DMA. */
+ if (hostdata->dma_setup(cmd, data_in_dir)) {
+ transfer_pio(regp, (uchar *) cmd->SCp.ptr,
+ cmd->SCp.this_residual, data_in_dir, hostdata);
+ } else {
+ /* We are able to do DMA (in fact, the Amiga hardware is
+ * already going!), so start up the wd33c93 in DMA mode.
+ * We set 'hostdata->dma' = D_DMA_RUNNING so that when the
+ * transfer completes and causes an interrupt, we're
+ * reminded to tell the Amiga to shut down its end. We'll
+ * postpone the updating of 'this_residual' and 'ptr'
+ * until then.
+ */
+ write_wd33c93(regp, WD_CONTROL, (CTRL_IDI | CTRL_EDI | CTRL_DMA));
+ /* write_wd33c93_count(regp, cmd->SCp.this_residual); */
+
+ if ((hostdata->level2 >= L2_DATA) || (cmd->SCp.phase == 0)) {
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ hostdata->state = S_RUNNING_LEVEL2;
+ } else {
+ write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
+ }
+ hostdata->dma = D_DMA_RUNNING;
+ }
}
-
+#ifdef CONFIG_SGI
+#define NOINTS_IN_WDINTR
+#endif
void wd33c93_intr (struct Scsi_Host *instance)
{
-struct WD33C93_hostdata *hostdata;
-Scsi_Cmnd *patch, *cmd;
-wd33c93_regs *regp;
-unsigned long flags;
-uchar asr, sr, phs, id, lun, *ucp, msg;
-unsigned long length;
-
-
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
- regp = hostdata->regp;
-
- asr = READ_AUX_STAT();
- if (!(asr & ASR_INT) || (asr & ASR_BSY))
- return;
-
-/* OK - it should be safe to re-enable system interrupts */
-
- save_flags(flags);
- sti();
-
- cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */
- sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear the interrupt */
- phs = read_wd33c93(regp, WD_COMMAND_PHASE);
-
-DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
-
-/* After starting a DMA transfer, the next interrupt
- * is guaranteed to be in response to completion of
- * the transfer. Since the Amiga DMA hardware runs in
- * in an open-ended fashion, it needs to be told when
- * to stop; do that here if D_DMA_RUNNING is true.
- * Also, we have to update 'this_residual' and 'ptr'
- * based on the contents of the TRANSFER_COUNT register,
- * in case the device decided to do an intermediate
- * disconnect (a device may do this if it has to do a
- * seek, or just to be nice and let other devices have
- * some bus time during long transfers). After doing
- * whatever is needed, we go on and service the WD3393
- * interrupt normally.
- */
-
- if (hostdata->dma == D_DMA_RUNNING) {
-DB(DB_TRANSFER,printk("[%p/%d:",cmd->SCp.ptr,cmd->SCp.this_residual))
- hostdata->dma_stop(cmd->host, cmd, 1);
- hostdata->dma = D_DMA_OFF;
- length = cmd->SCp.this_residual;
- cmd->SCp.this_residual = read_wd33c93_count(regp);
- cmd->SCp.ptr += (length - cmd->SCp.this_residual);
-DB(DB_TRANSFER,printk("%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual))
- }
-
-/* Respond to the specific WD3393 interrupt - there are quite a few! */
-
- switch (sr) {
-
- case CSR_TIMEOUT:
-DB(DB_INTR,printk("TIMEOUT"))
-
- cli();
- if (hostdata->state == S_RUNNING_LEVEL2)
- hostdata->connected = NULL;
- else {
- cmd = (Scsi_Cmnd *)hostdata->selecting; /* get a valid cmd */
- hostdata->selecting = NULL;
- }
-
- cmd->result = DID_NO_CONNECT << 16;
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- hostdata->state = S_UNCONNECTED;
- cmd->scsi_done(cmd);
-
-/* We are not connected to a target - check to see if there
- * are commands waiting to be executed.
- */
-
- sti();
- wd33c93_execute(instance);
- break;
-
-
-/* Note: this interrupt should not occur in a LEVEL2 command */
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ wd33c93_regs *regp = hostdata->regp;
+ Scsi_Cmnd *patch, *cmd;
+ uchar asr, sr, phs, id, lun, *ucp, msg;
+ unsigned long length;
+#ifndef NOINTS_IN_WDINTR
+ unsigned long flags;
+#endif
- case CSR_SELECT:
- cli();
-DB(DB_INTR,printk("SELECT"))
- hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
- hostdata->selecting = NULL;
+ asr = READ_AUX_STAT();
+ if (!(asr & ASR_INT) || (asr & ASR_BSY))
+ return;
- /* construct an IDENTIFY message with correct disconnect bit */
+#ifndef NOINTS_IN_WDINTR
+ /* OK - it should be safe to re-enable system interrupts */
+ save_flags(flags); sti();
+#endif
- hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);
- if (cmd->SCp.phase)
- hostdata->outgoing_msg[0] |= 0x40;
+ cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */
+ sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear the interrupt */
+ phs = read_wd33c93(regp, WD_COMMAND_PHASE);
+ DB(DB_INTR,printk("{%02x:%02x-", asr, sr));
+
+ /* After starting a DMA transfer, the next interrupt
+ * is guaranteed to be in response to completion of
+ * the transfer. Since the Amiga DMA hardware runs in
+ * in an open-ended fashion, it needs to be told when
+ * to stop; do that here if D_DMA_RUNNING is true.
+ * Also, we have to update 'this_residual' and 'ptr'
+ * based on the contents of the TRANSFER_COUNT register,
+ * in case the device decided to do an intermediate
+ * disconnect (a device may do this if it has to do a
+ * seek, or just to be nice and let other devices have
+ * some bus time during long transfers). After doing
+ * whatever is needed, we go on and service the WD3393
+ * interrupt normally.
+ */
+ if (hostdata->dma == D_DMA_RUNNING) {
+ DB(DB_TRANS,printk("[%p/%d:",cmd->SCp.ptr,cmd->SCp.this_residual));
+ hostdata->dma_stop(cmd->host, cmd, 1);
+ hostdata->dma = D_DMA_OFF;
+ length = cmd->SCp.this_residual;
+ cmd->SCp.this_residual = read_wd33c93_count(regp);
+ cmd->SCp.ptr += (length - cmd->SCp.this_residual);
+ DB(DB_TRANS,printk("%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual));
+ }
+
+ /* Respond to the specific WD3393 interrupt - there are quite a few! */
+ switch (sr) {
+ case CSR_TIMEOUT:
+ DB(DB_INTR, printk("TIMEOUT"));
+
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
+ if (hostdata->state == S_RUNNING_LEVEL2) {
+ hostdata->connected = NULL;
+ } else {
+ /* get a valid cmd */
+ cmd = (Scsi_Cmnd *) hostdata->selecting;
+ hostdata->selecting = NULL;
+ }
+ cmd->result = (DID_NO_CONNECT << 16);
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ hostdata->state = S_UNCONNECTED;
+ cmd->scsi_done(cmd);
+
+ /* We are not connected to a target - check to see if there
+ * are commands waiting to be executed.
+ */
+#ifndef NOINTS_IN_WDINTR
+ sti();
+#endif
+ wd33c93_execute(instance);
+ break;
- if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
+ case CSR_SELECT:
+ /* Note: this interrupt should not occur in a LEVEL2 command */
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
+ DB(DB_INTR, printk("SELECT"));
+ hostdata->connected = cmd = (Scsi_Cmnd *) hostdata->selecting;
+ hostdata->selecting = NULL;
+
+ /* construct an IDENTIFY message with correct disconnect bit */
+ hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);
+ if (cmd->SCp.phase)
+ hostdata->outgoing_msg[0] |= 0x40;
+ if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
#ifdef SYNC_DEBUG
-printk(" sending SDTR ");
+ printk(" sending SDTR ");
#endif
-
- hostdata->sync_stat[cmd->target] = SS_WAITING;
-
- /* tack on a 2nd message to ask about synchronous transfers */
-
- hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
- hostdata->outgoing_msg[2] = 3;
- hostdata->outgoing_msg[3] = EXTENDED_SDTR;
- hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
- hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
- hostdata->outgoing_len = 6;
- }
- else
- hostdata->outgoing_len = 1;
-
- hostdata->state = S_CONNECTED;
- break;
-
-
- case CSR_XFER_DONE|PHS_DATA_IN:
- case CSR_UNEXP |PHS_DATA_IN:
- case CSR_SRV_REQ |PHS_DATA_IN:
-DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
- transfer_bytes(regp, cmd, DATA_IN_DIR);
- if (hostdata->state != S_RUNNING_LEVEL2)
- hostdata->state = S_CONNECTED;
- break;
-
-
- case CSR_XFER_DONE|PHS_DATA_OUT:
- case CSR_UNEXP |PHS_DATA_OUT:
- case CSR_SRV_REQ |PHS_DATA_OUT:
-DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
- transfer_bytes(regp, cmd, DATA_OUT_DIR);
- if (hostdata->state != S_RUNNING_LEVEL2)
- hostdata->state = S_CONNECTED;
- break;
-
-
-/* Note: this interrupt should not occur in a LEVEL2 command */
-
- case CSR_XFER_DONE|PHS_COMMAND:
- case CSR_UNEXP |PHS_COMMAND:
- case CSR_SRV_REQ |PHS_COMMAND:
-DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
- transfer_pio(regp, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
- hostdata->state = S_CONNECTED;
- break;
-
-
- case CSR_XFER_DONE|PHS_STATUS:
- case CSR_UNEXP |PHS_STATUS:
- case CSR_SRV_REQ |PHS_STATUS:
-DB(DB_INTR,printk("STATUS"))
-
- cmd->SCp.Status = read_1_byte(regp);
- if (hostdata->level2 >= L2_BASIC) {
- sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear interrupt */
- hostdata->state = S_RUNNING_LEVEL2;
- write_wd33c93(regp, WD_COMMAND_PHASE, 0x50);
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- }
- else {
-DB(DB_INTR,printk("=%02x",cmd->SCp.Status))
- hostdata->state = S_CONNECTED;
- }
- break;
-
-
- case CSR_XFER_DONE|PHS_MESS_IN:
- case CSR_UNEXP |PHS_MESS_IN:
- case CSR_SRV_REQ |PHS_MESS_IN:
-DB(DB_INTR,printk("MSG_IN="))
-
- cli();
- msg = read_1_byte(regp);
- sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear interrupt */
-
- hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
- if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
- msg = EXTENDED_MESSAGE;
- else
- hostdata->incoming_ptr = 0;
-
- cmd->SCp.Message = msg;
- switch (msg) {
-
- case COMMAND_COMPLETE:
-DB(DB_INTR,printk("CCMP-%ld",cmd->pid))
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_PRE_CMP_DISC;
- break;
-
- case SAVE_POINTERS:
-DB(DB_INTR,printk("SDP"))
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- break;
-
- case RESTORE_POINTERS:
-DB(DB_INTR,printk("RDP"))
- if (hostdata->level2 >= L2_BASIC) {
- write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- hostdata->state = S_RUNNING_LEVEL2;
- }
- else {
- write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- }
- break;
-
- case DISCONNECT:
-DB(DB_INTR,printk("DIS"))
- cmd->device->disconnect = 1;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_PRE_TMP_DISC;
- break;
-
- case MESSAGE_REJECT:
-DB(DB_INTR,printk("REJ"))
+ hostdata->sync_stat[cmd->target] = SS_WAITING;
+
+ /* tack on a 2nd message to ask about
+ * synchronous transfers
+ */
+ hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
+ hostdata->outgoing_msg[2] = 3;
+ hostdata->outgoing_msg[3] = EXTENDED_SDTR;
+ hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
+ hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
+ hostdata->outgoing_len = 6;
+ } else {
+ hostdata->outgoing_len = 1;
+ }
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case CSR_XFER_DONE|PHS_DATA_IN:
+ case CSR_UNEXP |PHS_DATA_IN:
+ case CSR_SRV_REQ |PHS_DATA_IN:
+ DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual));
+ transfer_bytes(regp, cmd, DATA_IN_DIR);
+ if (hostdata->state != S_RUNNING_LEVEL2)
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case CSR_XFER_DONE|PHS_DATA_OUT:
+ case CSR_UNEXP |PHS_DATA_OUT:
+ case CSR_SRV_REQ |PHS_DATA_OUT:
+ DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual));
+ transfer_bytes(regp, cmd, DATA_OUT_DIR);
+ if (hostdata->state != S_RUNNING_LEVEL2)
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case CSR_XFER_DONE|PHS_COMMAND:
+ case CSR_UNEXP |PHS_COMMAND:
+ case CSR_SRV_REQ |PHS_COMMAND:
+ /* Note: this interrupt should not occur in a LEVEL2 command */
+ DB(DB_INTR,printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid));
+ transfer_pio(regp, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case CSR_XFER_DONE|PHS_STATUS:
+ case CSR_UNEXP |PHS_STATUS:
+ case CSR_SRV_REQ |PHS_STATUS:
+ DB(DB_INTR,printk("STATUS"));
+ cmd->SCp.Status = read_1_byte(regp);
+ if (hostdata->level2 >= L2_BASIC) {
+ /* clear interrupt */
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ hostdata->state = S_RUNNING_LEVEL2;
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0x50);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ } else {
+ DB(DB_INTR, printk("=%02x", cmd->SCp.Status));
+ hostdata->state = S_CONNECTED;
+ }
+ break;
+
+ case CSR_XFER_DONE|PHS_MESS_IN:
+ case CSR_UNEXP |PHS_MESS_IN:
+ case CSR_SRV_REQ |PHS_MESS_IN:
+ DB(DB_INTR, printk("MSG_IN="));
+
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
+ msg = read_1_byte(regp);
+ sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear interrupt */
+
+ hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
+ if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
+ msg = EXTENDED_MESSAGE;
+ else
+ hostdata->incoming_ptr = 0;
+
+ cmd->SCp.Message = msg;
+ switch (msg) {
+ case COMMAND_COMPLETE:
+ DB(DB_INTR,printk("CCMP-%ld", cmd->pid));
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_PRE_CMP_DISC;
+ break;
+
+ case SAVE_POINTERS:
+ DB(DB_INTR,printk("SDP"));
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case RESTORE_POINTERS:
+ DB(DB_INTR,printk("RDP"));
+ if (hostdata->level2 >= L2_BASIC) {
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ hostdata->state = S_RUNNING_LEVEL2;
+ } else {
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ }
+ break;
+
+ case DISCONNECT:
+ DB(DB_INTR,printk("DIS"));
+ cmd->device->disconnect = 1;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_PRE_TMP_DISC;
+ break;
+
+ case MESSAGE_REJECT:
+ DB(DB_INTR,printk("REJ"));
#ifdef SYNC_DEBUG
-printk("-REJ-");
+ printk("-REJ-");
#endif
- if (hostdata->sync_stat[cmd->target] == SS_WAITING)
- hostdata->sync_stat[cmd->target] = SS_SET;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- break;
-
- case EXTENDED_MESSAGE:
-DB(DB_INTR,printk("EXT"))
-
- ucp = hostdata->incoming_msg;
-
+ if (hostdata->sync_stat[cmd->target] == SS_WAITING)
+ hostdata->sync_stat[cmd->target] = SS_SET;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case EXTENDED_MESSAGE:
+ DB(DB_INTR,printk("EXT"));
+ ucp = hostdata->incoming_msg;
#ifdef SYNC_DEBUG
-printk("%02x",ucp[hostdata->incoming_ptr]);
+ printk("%02x",ucp[hostdata->incoming_ptr]);
#endif
- /* Is this the last byte of the extended message? */
-
- if ((hostdata->incoming_ptr >= 2) &&
- (hostdata->incoming_ptr == (ucp[1] + 1))) {
-
- switch (ucp[2]) { /* what's the EXTENDED code? */
- case EXTENDED_SDTR:
- id = calc_sync_xfer(ucp[3],ucp[4]);
- if (hostdata->sync_stat[cmd->target] != SS_WAITING) {
-
-/* A device has sent an unsolicited SDTR message; rather than go
- * through the effort of decoding it and then figuring out what
- * our reply should be, we're just gonna say that we have a
- * synchronous fifo depth of 0. This will result in asynchronous
- * transfers - not ideal but so much easier.
- * Actually, this is OK because it assures us that if we don't
- * specifically ask for sync transfers, we won't do any.
- */
-
- write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
- hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
- hostdata->outgoing_msg[1] = 3;
- hostdata->outgoing_msg[2] = EXTENDED_SDTR;
- hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;
- hostdata->outgoing_msg[4] = 0;
- hostdata->outgoing_len = 5;
- hostdata->sync_xfer[cmd->target] =
- calc_sync_xfer(hostdata->default_sx_per/4,0);
- }
- else {
- hostdata->sync_xfer[cmd->target] = id;
- }
+ /* Is this the last byte of the extended message? */
+ if ((hostdata->incoming_ptr >= 2) &&
+ (hostdata->incoming_ptr == (ucp[1] + 1))) {
+ switch (ucp[2]) { /* what's the EXTENDED code? */
+ case EXTENDED_SDTR:
+ id = calc_sync_xfer(ucp[3],ucp[4]);
+ if (hostdata->sync_stat[cmd->target] !=
+ SS_WAITING) {
+ /* A device has sent
+ * an unsolicited SDTR
+ * message; rather
+ * than go through the
+ * effort of decoding
+ * it and then
+ * figuring out what
+ * our reply should
+ * be, we're just
+ * gonna say that we
+ * have a synchronous
+ * fifo depth of
+ * 0. This will result
+ * in asynchronous
+ * transfers - not
+ * ideal but so much
+ * easier. Actually,
+ * this is OK because
+ * it assures us that
+ * if we don't
+ * specifically ask
+ * for sync transfers,
+ * we won't do any. */
+
+ /* want MESS_OUT */
+ write_wd33c93_cmd(regp,
+ WD_CMD_ASSERT_ATN);
+ hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
+ hostdata->outgoing_msg[1] = 3;
+ hostdata->outgoing_msg[2] = EXTENDED_SDTR;
+ hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;
+ hostdata->outgoing_msg[4] = 0;
+ hostdata->outgoing_len = 5;
+ hostdata->sync_xfer[cmd->target] =
+ calc_sync_xfer(hostdata->default_sx_per/4,0);
+ } else {
+ hostdata->sync_xfer[cmd->target] = id;
+ }
#ifdef SYNC_DEBUG
-printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
+ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
+#endif
+ hostdata->sync_stat[cmd->target] = SS_SET;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case EXTENDED_WDTR:
+ /* want MESS_OUT */
+ write_wd33c93_cmd(regp, WD_CMD_ASSERT_ATN);
+ printk("sending WDTR ");
+ hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
+ hostdata->outgoing_msg[1] = 2;
+ hostdata->outgoing_msg[2] = EXTENDED_WDTR;
+ /* 8 bit transfer width */
+ hostdata->outgoing_msg[3] = 0;
+ hostdata->outgoing_len = 4;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ break;
+
+ default:
+ /* want MESS_OUT */
+ write_wd33c93_cmd(regp, WD_CMD_ASSERT_ATN);
+ printk("Rejecting Unknown Extended "
+ "Message(%02x). ",ucp[2]);
+ hostdata->outgoing_msg[0] = MESSAGE_REJECT;
+ hostdata->outgoing_len = 1;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ break;
+ }
+ hostdata->incoming_ptr = 0;
+ } else {
+ /* We need to read more MESS_IN bytes for the
+ * extended message
+ */
+ hostdata->incoming_ptr++;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ }
+ break;
+
+ default:
+ printk("Rejecting Unknown Message(%02x) ",msg);
+ /* want MESS_OUT */
+ write_wd33c93_cmd(regp, WD_CMD_ASSERT_ATN);
+ hostdata->outgoing_msg[0] = MESSAGE_REJECT;
+ hostdata->outgoing_len = 1;
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ hostdata->state = S_CONNECTED;
+ }
+ break;
+
+
+ case CSR_SEL_XFER_DONE:
+ /* Note: this interrupt will occur only after a LEVEL2 command */
+#ifndef NOINTS_IN_WDINTR
+ cli();
#endif
- hostdata->sync_stat[cmd->target] = SS_SET;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- break;
- case EXTENDED_WDTR:
- write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
- printk("sending WDTR ");
- hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
- hostdata->outgoing_msg[1] = 2;
- hostdata->outgoing_msg[2] = EXTENDED_WDTR;
- hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */
- hostdata->outgoing_len = 4;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- break;
- default:
- write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
- printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);
- hostdata->outgoing_msg[0] = MESSAGE_REJECT;
- hostdata->outgoing_len = 1;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- break;
- }
- hostdata->incoming_ptr = 0;
- }
-
- /* We need to read more MESS_IN bytes for the extended message */
-
- else {
- hostdata->incoming_ptr++;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- }
- break;
-
- default:
- printk("Rejecting Unknown Message(%02x) ",msg);
- write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
- hostdata->outgoing_msg[0] = MESSAGE_REJECT;
- hostdata->outgoing_len = 1;
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- hostdata->state = S_CONNECTED;
- }
- break;
-
-
-/* Note: this interrupt will occur only after a LEVEL2 command */
-
- case CSR_SEL_XFER_DONE:
- cli();
-
-/* Make sure that reselection is enabled at this point - it may
- * have been turned off for the command that just completed.
- */
-
- write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
- if (phs == 0x60) {
-DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))
- cmd->SCp.Message = COMMAND_COMPLETE;
- lun = read_wd33c93(regp, WD_TARGET_LUN);
- if (cmd->SCp.Status == GOOD)
- cmd->SCp.Status = lun;
- hostdata->connected = NULL;
- if (cmd->cmnd[0] != REQUEST_SENSE)
- cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- else if (cmd->SCp.Status != GOOD)
- cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- hostdata->state = S_UNCONNECTED;
- cmd->scsi_done(cmd);
-
-/* We are no longer connected to a target - check to see if
- * there are commands waiting to be executed.
- */
-
- wd33c93_execute(instance);
- }
- else {
- printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
- }
- break;
-
-
-/* Note: this interrupt will occur only after a LEVEL2 command */
-
- case CSR_SDP:
-DB(DB_INTR,printk("SDP"))
- hostdata->state = S_RUNNING_LEVEL2;
- write_wd33c93(regp, WD_COMMAND_PHASE, 0x41);
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- break;
-
-
- case CSR_XFER_DONE|PHS_MESS_OUT:
- case CSR_UNEXP |PHS_MESS_OUT:
- case CSR_SRV_REQ |PHS_MESS_OUT:
-DB(DB_INTR,printk("MSG_OUT="))
-
-/* To get here, we've probably requested MESSAGE_OUT and have
- * already put the correct bytes in outgoing_msg[] and filled
- * in outgoing_len. We simply send them out to the SCSI bus.
- * Sometimes we get MESSAGE_OUT phase when we're not expecting
- * it - like when our SDTR message is rejected by a target. Some
- * targets send the REJECT before receiving all of the extended
- * message, and then seem to go back to MESSAGE_OUT for a byte
- * or two. Not sure why, or if I'm doing something wrong to
- * cause this to happen. Regardless, it seems that sending
- * NOP messages in these situations results in no harm and
- * makes everyone happy.
- */
-
- if (hostdata->outgoing_len == 0) {
- hostdata->outgoing_len = 1;
- hostdata->outgoing_msg[0] = NOP;
- }
- transfer_pio(regp, hostdata->outgoing_msg, hostdata->outgoing_len,
- DATA_OUT_DIR, hostdata);
-DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
- hostdata->outgoing_len = 0;
- hostdata->state = S_CONNECTED;
- break;
-
-
- case CSR_UNEXP_DISC:
-
-/* I think I've seen this after a request-sense that was in response
- * to an error condition, but not sure. We certainly need to do
- * something when we get this interrupt - the question is 'what?'.
- * Let's think positively, and assume some command has finished
- * in a legal manner (like a command that provokes a request-sense),
- * so we treat it as a normal command-complete-disconnect.
- */
-
- cli();
-
-/* Make sure that reselection is enabled at this point - it may
- * have been turned off for the command that just completed.
- */
-
- write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
- if (cmd == NULL) {
- printk(" - Already disconnected! ");
- hostdata->state = S_UNCONNECTED;
- return;
- }
-DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
- hostdata->connected = NULL;
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- hostdata->state = S_UNCONNECTED;
- if (cmd->cmnd[0] != REQUEST_SENSE)
- cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- else if (cmd->SCp.Status != GOOD)
- cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
- cmd->scsi_done(cmd);
-
-/* We are no longer connected to a target - check to see if
- * there are commands waiting to be executed.
- */
-
- wd33c93_execute(instance);
- break;
-
-
- case CSR_DISC:
- cli();
-/* Make sure that reselection is enabled at this point - it may
- * have been turned off for the command that just completed.
- */
+ /* Make sure that reselection is enabled at this point - it may
+ * have been turned off for the command that just completed.
+ */
+ write_wd33c93(regp, WD_SOURCE_ID, SRCID_ER);
+ if (phs == 0x60) {
+ DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid));
+ cmd->SCp.Message = COMMAND_COMPLETE;
+ lun = read_wd33c93(regp, WD_TARGET_LUN);
+ if (cmd->SCp.Status == GOOD)
+ cmd->SCp.Status = lun;
+ hostdata->connected = NULL;
+ if (cmd->cmnd[0] != REQUEST_SENSE)
+ cmd->result = (cmd->SCp.Status |
+ (cmd->SCp.Message << 8));
+ else if (cmd->SCp.Status != GOOD)
+ cmd->result = ((cmd->result & 0x00ffff) |
+ (DID_ERROR << 16));
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ hostdata->state = S_UNCONNECTED;
+ cmd->scsi_done(cmd);
+
+ /* We are no longer connected to a target - check to see if
+ * there are commands waiting to be executed.
+ */
+ wd33c93_execute(instance);
+ } else {
+ printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE "
+ "phase!!---", asr, sr, phs, cmd->pid);
+ }
+ break;
+
+ case CSR_SDP:
+ /* Note: this interrupt will occur only after a LEVEL2 command */
+ DB(DB_INTR, printk("SDP"));
+ hostdata->state = S_RUNNING_LEVEL2;
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0x41);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ break;
+
+ case CSR_XFER_DONE|PHS_MESS_OUT:
+ case CSR_UNEXP |PHS_MESS_OUT:
+ case CSR_SRV_REQ |PHS_MESS_OUT:
+ DB(DB_INTR, printk("MSG_OUT="));
+
+ /* To get here, we've probably requested MESSAGE_OUT and have
+ * already put the correct bytes in outgoing_msg[] and filled
+ * in outgoing_len. We simply send them out to the SCSI bus.
+ * Sometimes we get MESSAGE_OUT phase when we're not expecting
+ * it - like when our SDTR message is rejected by a target. Some
+ * targets send the REJECT before receiving all of the extended
+ * message, and then seem to go back to MESSAGE_OUT for a byte
+ * or two. Not sure why, or if I'm doing something wrong to
+ * cause this to happen. Regardless, it seems that sending
+ * NOP messages in these situations results in no harm and
+ * makes everyone happy.
+ */
+ if (hostdata->outgoing_len == 0) {
+ hostdata->outgoing_len = 1;
+ hostdata->outgoing_msg[0] = NOP;
+ }
+ transfer_pio(regp, hostdata->outgoing_msg, hostdata->outgoing_len,
+ DATA_OUT_DIR, hostdata);
+ DB(DB_INTR,printk("%02x", hostdata->outgoing_msg[0]));
+ hostdata->outgoing_len = 0;
+ hostdata->state = S_CONNECTED;
+ break;
+
+ case CSR_UNEXP_DISC:
+ /* I think I've seen this after a request-sense that was in response
+ * to an error condition, but not sure. We certainly need to do
+ * something when we get this interrupt - the question is 'what?'.
+ * Let's think positively, and assume some command has finished
+ * in a legal manner (like a command that provokes a request-sense),
+ * so we treat it as a normal command-complete-disconnect.
+ */
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
- write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
-DB(DB_INTR,printk("DISC-%ld",cmd->pid))
- if (cmd == NULL) {
- printk(" - Already disconnected! ");
- hostdata->state = S_UNCONNECTED;
- }
- switch (hostdata->state) {
- case S_PRE_CMP_DISC:
- hostdata->connected = NULL;
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- hostdata->state = S_UNCONNECTED;
- if (cmd->cmnd[0] != REQUEST_SENSE)
- cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- else if (cmd->SCp.Status != GOOD)
- cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
- cmd->scsi_done(cmd);
- break;
- case S_PRE_TMP_DISC:
- case S_RUNNING_LEVEL2:
- cmd->host_scribble = (uchar *)hostdata->disconnected_Q;
- hostdata->disconnected_Q = cmd;
- hostdata->connected = NULL;
- hostdata->state = S_UNCONNECTED;
+ /* Make sure that reselection is enabled at this point - it may
+ * have been turned off for the command that just completed.
+ */
+ write_wd33c93(regp, WD_SOURCE_ID, SRCID_ER);
+ if (cmd == NULL) {
+ printk(" - Already disconnected! ");
+ hostdata->state = S_UNCONNECTED;
+ return;
+ }
+ DB(DB_INTR,printk("UNEXP_DISC-%ld", cmd->pid));
+ hostdata->connected = NULL;
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ hostdata->state = S_UNCONNECTED;
+ if (cmd->cmnd[0] != REQUEST_SENSE)
+ cmd->result = (cmd->SCp.Status | (cmd->SCp.Message << 8));
+ else if (cmd->SCp.Status != GOOD)
+ cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
+ cmd->scsi_done(cmd);
+
+ /* We are no longer connected to a target - check to see if
+ * there are commands waiting to be executed.
+ */
+ wd33c93_execute(instance);
+ break;
+
+ case CSR_DISC:
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
+ /* Make sure that reselection is enabled at this point - it may
+ * have been turned off for the command that just completed.
+ */
+ write_wd33c93(regp, WD_SOURCE_ID, SRCID_ER);
+ DB(DB_INTR, printk("DISC-%ld", cmd->pid));
+ if (cmd == NULL) {
+ printk(" - Already disconnected! ");
+ hostdata->state = S_UNCONNECTED;
+ }
+ switch (hostdata->state) {
+ case S_PRE_CMP_DISC:
+ hostdata->connected = NULL;
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ hostdata->state = S_UNCONNECTED;
+ if (cmd->cmnd[0] != REQUEST_SENSE)
+ cmd->result = (cmd->SCp.Status |
+ (cmd->SCp.Message << 8));
+ else if (cmd->SCp.Status != GOOD)
+ cmd->result = ((cmd->result & 0x00ffff) |
+ (DID_ERROR << 16));
+ cmd->scsi_done(cmd);
+ break;
+ case S_PRE_TMP_DISC:
+ case S_RUNNING_LEVEL2:
+ cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
+ hostdata->disconnected_Q = cmd;
+ hostdata->connected = NULL;
+ hostdata->state = S_UNCONNECTED;
#ifdef PROC_INTERFACE
- disc_taken_total++;
+ disc_taken_total++;
#endif
+ break;
- break;
- default:
- printk("*** Unexpected DISCONNECT interrupt! ***");
- hostdata->state = S_UNCONNECTED;
- }
+ default:
+ printk("*** Unexpected DISCONNECT interrupt! ***");
+ hostdata->state = S_UNCONNECTED;
+ }
-/* We are no longer connected to a target - check to see if
- * there are commands waiting to be executed.
- */
+ /* We are no longer connected to a target - check to see if
+ * there are commands waiting to be executed.
+ */
+ wd33c93_execute(instance);
+ break;
- wd33c93_execute(instance);
- break;
-
-
- case CSR_RESEL_AM:
-DB(DB_INTR,printk("RESEL"))
-
- cli();
-
- /* First we have to make sure this reselection didn't */
- /* happen during Arbitration/Selection of some other device. */
- /* If yes, put losing command back on top of input_Q. */
-
- if (hostdata->level2 <= L2_NONE) {
-
- if (hostdata->selecting) {
- cmd = (Scsi_Cmnd *)hostdata->selecting;
- hostdata->selecting = NULL;
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- cmd->host_scribble = (uchar *)hostdata->input_Q;
- hostdata->input_Q = cmd;
- }
- }
-
- else {
-
- if (cmd) {
- if (phs == 0x00) {
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- cmd->host_scribble = (uchar *)hostdata->input_Q;
- hostdata->input_Q = cmd;
- }
- else {
- printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);
- while (1)
- printk("\r");
- }
- }
-
- }
-
- /* OK - find out which device reselected us. */
-
- id = read_wd33c93(regp, WD_SOURCE_ID);
- id &= SRCID_MASK;
-
- /* and extract the lun from the ID message. (Note that we don't
- * bother to check for a valid message here - I guess this is
- * not the right way to go, but...)
- */
-
- lun = read_wd33c93(regp, WD_DATA);
- if (hostdata->level2 < L2_RESELECT)
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- lun &= 7;
-
- /* Now we look for the command that's reconnecting. */
-
- cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;
- patch = NULL;
- while (cmd) {
- if (id == cmd->target && lun == cmd->lun)
- break;
- patch = cmd;
- cmd = (Scsi_Cmnd *)cmd->host_scribble;
- }
-
- /* Hmm. Couldn't find a valid command.... What to do? */
-
- if (!cmd) {
- printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
- return;
- }
-
- /* Ok, found the command - now start it up again. */
-
- if (patch)
- patch->host_scribble = cmd->host_scribble;
- else
- hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;
- hostdata->connected = cmd;
-
- /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'
- * because these things are preserved over a disconnect.
- * But we DO need to fix the DPD bit so it's correct for this command.
- */
-
- if (IS_DIR_OUT(cmd))
- write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
- else
- write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
- if (hostdata->level2 >= L2_RESELECT) {
- write_wd33c93_count(regp, 0); /* we want a DATA_PHASE interrupt */
- write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
- write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
- hostdata->state = S_RUNNING_LEVEL2;
- }
- else
- hostdata->state = S_CONNECTED;
-
-DB(DB_INTR,printk("-%ld",cmd->pid))
- break;
-
- default:
- printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
- }
-
- restore_flags(flags);
+ case CSR_RESEL_AM:
+ DB(DB_INTR,printk("RESEL"));
-DB(DB_INTR,printk("} "))
+#ifndef NOINTS_IN_WDINTR
+ cli();
+#endif
+ /* First we have to make sure this reselection didn't
+ * happen during Arbitration/Selection of some other device.
+ * If yes, put losing command back on top of input_Q.
+ */
+ if (hostdata->level2 <= L2_NONE) {
+ if (hostdata->selecting) {
+ cmd = (Scsi_Cmnd *) hostdata->selecting;
+ hostdata->selecting = NULL;
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ cmd->host_scribble = (uchar *) hostdata->input_Q;
+ hostdata->input_Q = cmd;
+ }
+ } else {
+ if (cmd) {
+ if (phs == 0x00) {
+ hostdata->busy[cmd->target] &=
+ ~(1 << cmd->lun);
+ cmd->host_scribble =
+ (uchar *) hostdata->input_Q;
+ hostdata->input_Q = cmd;
+ } else {
+ printk("---%02x:%02x:%02x-TROUBLE: "
+ "Intrusive ReSelect!---",
+ asr, sr, phs);
+ while (1)
+ printk("\r");
+ }
+ }
+ }
+
+ /* OK - find out which device reselected us. */
+ id = read_wd33c93(regp, WD_SOURCE_ID);
+ id &= SRCID_MASK;
+
+ /* and extract the lun from the ID message. (Note that we don't
+ * bother to check for a valid message here - I guess this is
+ * not the right way to go, but...)
+ */
+ lun = read_wd33c93(regp, WD_DATA);
+ if (hostdata->level2 < L2_RESELECT)
+ write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
+ lun &= 7;
+
+ /* Now we look for the command that's reconnecting. */
+ cmd = (Scsi_Cmnd *) hostdata->disconnected_Q;
+ patch = NULL;
+ while (cmd) {
+ if ((id == cmd->target) && (lun == cmd->lun))
+ break;
+ patch = cmd;
+ cmd = (Scsi_Cmnd *) cmd->host_scribble;
+ }
+
+ /* Hmm. Couldn't find a valid command.... What to do? */
+ if (!cmd) {
+ printk("---TROUBLE: target %d.%d not in disconnect "
+ "queue---", id, lun);
+ return;
+ }
+
+ /* Ok, found the command - now start it up again. */
+ if (patch)
+ patch->host_scribble = cmd->host_scribble;
+ else
+ hostdata->disconnected_Q = (Scsi_Cmnd *) cmd->host_scribble;
+ hostdata->connected = cmd;
+
+ /* We don't need to worry about 'initialize_SCp()' or
+ * 'hostdata->busy[]' because these things are preserved
+ * over a disconnect. But we DO need to fix the DPD bit so
+ * it's correct for this command.
+ */
+ if (IS_DIR_OUT(cmd))
+ write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
+ else
+ write_wd33c93(regp, WD_DESTINATION_ID,
+ (cmd->target | DSTID_DPD));
+ if (hostdata->level2 >= L2_RESELECT) {
+ /* we want a DATA_PHASE interrupt */
+ write_wd33c93_count(regp, 0);
+ write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
+ write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
+ hostdata->state = S_RUNNING_LEVEL2;
+ } else {
+ hostdata->state = S_CONNECTED;
+ }
+
+ DB(DB_INTR,printk("-%ld", cmd->pid));
+ break;
+
+ default:
+ printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
+ }
+#ifndef NOINTS_IN_WDINTR
+ restore_flags(flags);
+#endif
+ DB(DB_INTR,printk("} "));
}
-
-
void reset_wd33c93(struct Scsi_Host *instance)
{
-struct WD33C93_hostdata *hostdata;
-wd33c93_regs *regp;
-uchar sr;
-
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
- regp = hostdata->regp;
-
- write_wd33c93(regp, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
- instance->this_id | hostdata->clock_freq);
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
- write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
- calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
- write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET);
-
- while (!(READ_AUX_STAT() & ASR_INT))
- ;
- sr = read_wd33c93(regp, WD_SCSI_STATUS);
-
- hostdata->microcode = read_wd33c93(regp, WD_CDB_1);
- if (sr == 0x00)
- hostdata->chip = C_WD33C93;
- else if (sr == 0x01) {
- write_wd33c93(regp, WD_QUEUE_TAG, 0xa5); /* any random number */
- sr = read_wd33c93(regp, WD_QUEUE_TAG);
- if (sr == 0xa5) {
- hostdata->chip = C_WD33C93B;
- write_wd33c93(regp, WD_QUEUE_TAG, 0);
- }
- else
- hostdata->chip = C_WD33C93A;
- }
- else
- hostdata->chip = C_UNKNOWN_CHIP;
-
- write_wd33c93(regp, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ wd33c93_regs *regp = hostdata->regp;
+ uchar sr;
+
+ write_wd33c93(regp, WD_OWN_ID, (OWNID_EAF | OWNID_RAF |
+ instance->this_id | hostdata->clock_freq));
+ write_wd33c93(regp, WD_CONTROL, (CTRL_IDI | CTRL_EDI | CTRL_POLLED));
+ write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
+ calc_sync_xfer(hostdata->default_sx_per/4, DEFAULT_SX_OFF));
+ write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET);
+
+ while (!(READ_AUX_STAT() & ASR_INT))
+ ;
+
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ hostdata->microcode = read_wd33c93(regp, WD_CDB_1);
+ if (sr == 0x00)
+ hostdata->chip = C_WD33C93;
+ else if (sr == 0x01) {
+ write_wd33c93(regp, WD_QUEUE_TAG, 0xa5); /* any random number */
+ sr = read_wd33c93(regp, WD_QUEUE_TAG);
+ if (sr == 0xa5) {
+ hostdata->chip = C_WD33C93B;
+ write_wd33c93(regp, WD_QUEUE_TAG, 0);
+ } else {
+ hostdata->chip = C_WD33C93A;
+ }
+ } else {
+ hostdata->chip = C_UNKNOWN_CHIP;
+ }
+
+ write_wd33c93(regp, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
+ write_wd33c93(regp, WD_CONTROL, (CTRL_IDI | CTRL_EDI | CTRL_POLLED));
}
-
-
#if LINUX_VERSION_CODE >= 0x010300
int wd33c93_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
#else
int wd33c93_reset(Scsi_Cmnd *SCpnt)
#endif
{
-unsigned long flags;
-struct Scsi_Host *instance;
-struct WD33C93_hostdata *hostdata;
-int i;
-
- instance = SCpnt->host;
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
-
- printk("scsi%d: reset. ", instance->host_no);
- save_flags(flags);
- cli();
-
- ((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);
- for (i = 0; i < 8; i++) {
- hostdata->busy[i] = 0;
- hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
- hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
- }
- hostdata->input_Q = NULL;
- hostdata->selecting = NULL;
- hostdata->connected = NULL;
- hostdata->disconnected_Q = NULL;
- hostdata->state = S_UNCONNECTED;
- hostdata->dma = D_DMA_OFF;
- hostdata->incoming_ptr = 0;
- hostdata->outgoing_len = 0;
-
- reset_wd33c93(instance);
- SCpnt->result = DID_RESET << 16;
- restore_flags(flags);
- return 0;
+ struct Scsi_Host *instance = SCpnt->host;
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ unsigned long flags;
+ int i;
+
+ printk("scsi%d: reset. ", instance->host_no);
+ save_flags(flags);
+ cli();
+
+ ((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);
+ for (i = 0; i < 8; i++) {
+ hostdata->busy[i] = 0;
+ hostdata->sync_xfer[i] =
+ calc_sync_xfer(DEFAULT_SX_PER/4, DEFAULT_SX_OFF);
+ hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
+ }
+ hostdata->input_Q = NULL;
+ hostdata->selecting = NULL;
+ hostdata->connected = NULL;
+ hostdata->disconnected_Q = NULL;
+ hostdata->state = S_UNCONNECTED;
+ hostdata->dma = D_DMA_OFF;
+ hostdata->incoming_ptr = 0;
+ hostdata->outgoing_len = 0;
+
+ reset_wd33c93(instance);
+ SCpnt->result = (DID_RESET << 16);
+ restore_flags(flags);
+ return 0;
}
-
-
int wd33c93_abort (Scsi_Cmnd *cmd)
{
-struct Scsi_Host *instance;
-struct WD33C93_hostdata *hostdata;
-wd33c93_regs *regp;
-Scsi_Cmnd *tmp, *prev;
-unsigned long flags;
-
- save_flags (flags);
- cli();
-
- instance = cmd->host;
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
- regp = hostdata->regp;
-
-/*
- * Case 1 : If the command hasn't been issued yet, we simply remove it
- * from the input_Q.
- */
-
- tmp = (Scsi_Cmnd *)hostdata->input_Q;
- prev = 0;
- while (tmp) {
- if (tmp == cmd) {
- if (prev)
- prev->host_scribble = cmd->host_scribble;
- cmd->host_scribble = NULL;
- cmd->result = DID_ABORT << 16;
- printk("scsi%d: Abort - removing command %ld from input_Q. ",
- instance->host_no, cmd->pid);
- cmd->scsi_done(cmd);
- restore_flags(flags);
- return SCSI_ABORT_SUCCESS;
- }
- prev = tmp;
- tmp = (Scsi_Cmnd *)tmp->host_scribble;
- }
-
-/*
- * Case 2 : If the command is connected, we're going to fail the abort
- * and let the high level SCSI driver retry at a later time or
- * issue a reset.
- *
- * Timeouts, and therefore aborted commands, will be highly unlikely
- * and handling them cleanly in this situation would make the common
- * case of noresets less efficient, and would pollute our code. So,
- * we fail.
- */
-
- if (hostdata->connected == cmd) {
- uchar sr, asr;
- unsigned long timeout;
-
- printk("scsi%d: Aborting connected command %ld - ",
- instance->host_no, cmd->pid);
-
- printk("stopping DMA - ");
- if (hostdata->dma == D_DMA_RUNNING) {
- hostdata->dma_stop(instance, cmd, 0);
- hostdata->dma = D_DMA_OFF;
- }
-
- printk("sending wd33c93 ABORT command - ");
- write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
- write_wd33c93_cmd(regp, WD_CMD_ABORT);
-
-/* Now we have to attempt to flush out the FIFO... */
-
- printk("flushing fifo - ");
- timeout = 1000000;
- do {
- asr = READ_AUX_STAT();
- if (asr & ASR_DBR)
- read_wd33c93(regp, WD_DATA);
- } while (!(asr & ASR_INT) && timeout-- > 0);
- sr = read_wd33c93(regp, WD_SCSI_STATUS);
- printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
- asr, sr, read_wd33c93_count(regp), timeout);
-
- /*
- * Abort command processed.
- * Still connected.
- * We must disconnect.
- */
-
- printk("sending wd33c93 DISCONNECT command - ");
- write_wd33c93_cmd(regp, WD_CMD_DISCONNECT);
-
- timeout = 1000000;
- asr = READ_AUX_STAT();
- while ((asr & ASR_CIP) && timeout-- > 0)
- asr = READ_AUX_STAT();
- sr = read_wd33c93(regp, WD_SCSI_STATUS);
- printk("asr=%02x, sr=%02x.",asr,sr);
-
- hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
- hostdata->connected = NULL;
- hostdata->state = S_UNCONNECTED;
- cmd->result = DID_ABORT << 16;
- cmd->scsi_done(cmd);
-
-/* sti();*/
- wd33c93_execute (instance);
-
- restore_flags(flags);
- return SCSI_ABORT_SUCCESS;
- }
-
-/*
- * Case 3: If the command is currently disconnected from the bus,
- * we're not going to expend much effort here: Let's just return
- * an ABORT_SNOOZE and hope for the best...
- */
-
- tmp = (Scsi_Cmnd *)hostdata->disconnected_Q;
- while (tmp) {
- if (tmp == cmd) {
- printk("scsi%d: Abort - command %ld found on disconnected_Q - ",
- instance->host_no, cmd->pid);
- printk("returning ABORT_SNOOZE. ");
- restore_flags(flags);
- return SCSI_ABORT_SNOOZE;
- }
- tmp = (Scsi_Cmnd *)tmp->host_scribble;
- }
-
-/*
- * Case 4 : If we reached this point, the command was not found in any of
- * the queues.
- *
- * We probably reached this point because of an unlikely race condition
- * between the command completing successfully and the abortion code,
- * so we won't panic, but we will notify the user in case something really
- * broke.
- */
-
-/* sti();*/
- wd33c93_execute (instance);
-
- restore_flags(flags);
- printk("scsi%d: warning : SCSI command probably completed successfully"
- " before abortion. ", instance->host_no);
- return SCSI_ABORT_NOT_RUNNING;
+ struct Scsi_Host *instance = cmd->host;
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ wd33c93_regs *regp = hostdata->regp;
+ Scsi_Cmnd *tmp, *prev;
+ unsigned long flags;
+
+ save_flags (flags);
+ cli();
+
+ /* Case 1 : If the command hasn't been issued yet, we simply remove it
+ * from the input_Q.
+ */
+ tmp = (Scsi_Cmnd *) hostdata->input_Q;
+ prev = 0;
+ while (tmp) {
+ if (tmp == cmd) {
+ if (prev)
+ prev->host_scribble = cmd->host_scribble;
+ cmd->host_scribble = NULL;
+ cmd->result = (DID_ABORT << 16);
+ printk("scsi%d: Abort - removing command %ld from "
+ "input_Q. ", instance->host_no, cmd->pid);
+ cmd->scsi_done(cmd);
+ restore_flags(flags);
+ return SCSI_ABORT_SUCCESS;
+ }
+ prev = tmp;
+ tmp = (Scsi_Cmnd *) tmp->host_scribble;
+ }
+
+ /* Case 2 : If the command is connected, we're going to fail the abort
+ * and let the high level SCSI driver retry at a later time or
+ * issue a reset.
+ *
+ * Timeouts, and therefore aborted commands, will be highly unlikely
+ * and handling them cleanly in this situation would make the common
+ * case of noresets less efficient, and would pollute our code. So,
+ * we fail.
+ */
+ if (hostdata->connected == cmd) {
+ uchar sr, asr;
+ unsigned long timeout;
+
+ printk("scsi%d: Aborting connected command %ld - ",
+ instance->host_no, cmd->pid);
+
+ printk("stopping DMA - ");
+ if (hostdata->dma == D_DMA_RUNNING) {
+ hostdata->dma_stop(instance, cmd, 0);
+ hostdata->dma = D_DMA_OFF;
+ }
+
+ printk("sending wd33c93 ABORT command - ");
+ write_wd33c93(regp, WD_CONTROL,
+ (CTRL_IDI | CTRL_EDI | CTRL_POLLED));
+ write_wd33c93_cmd(regp, WD_CMD_ABORT);
+
+ /* Now we have to attempt to flush out the FIFO... */
+ printk("flushing fifo - ");
+ timeout = 1000000;
+ do {
+ asr = READ_AUX_STAT();
+ if (asr & ASR_DBR)
+ read_wd33c93(regp, WD_DATA);
+ } while (!(asr & ASR_INT) && timeout-- > 0);
+
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ printk("asr=%02x, sr=%02x, %ld bytes un-transferred "
+ "(timeout=%ld) - ", asr, sr, read_wd33c93_count(regp),
+ timeout);
+
+ /* Abort command processed.
+ * Still connected.
+ * We must disconnect.
+ */
+ printk("sending wd33c93 DISCONNECT command - ");
+ write_wd33c93_cmd(regp, WD_CMD_DISCONNECT);
+
+ timeout = 1000000;
+ asr = READ_AUX_STAT();
+ while ((asr & ASR_CIP) && timeout-- > 0)
+ asr = READ_AUX_STAT();
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ printk("asr=%02x, sr=%02x.", asr, sr);
+
+ hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+ hostdata->connected = NULL;
+ hostdata->state = S_UNCONNECTED;
+ cmd->result = (DID_ABORT << 16);
+ cmd->scsi_done(cmd);
+
+ /* sti();*/
+ wd33c93_execute (instance);
+
+ restore_flags(flags);
+ return SCSI_ABORT_SUCCESS;
+ }
+
+ /* Case 3: If the command is currently disconnected from the bus,
+ * we're not going to expend much effort here: Let's just return
+ * an ABORT_SNOOZE and hope for the best...
+ */
+
+ tmp = (Scsi_Cmnd *) hostdata->disconnected_Q;
+ while (tmp) {
+ if (tmp == cmd) {
+ printk("scsi%d: Abort - command %ld found on "
+ "disconnected_Q - ", instance->host_no, cmd->pid);
+ printk("returning ABORT_SNOOZE. ");
+ restore_flags(flags);
+ return SCSI_ABORT_SNOOZE;
+ }
+ tmp = (Scsi_Cmnd *) tmp->host_scribble;
+ }
+
+ /* Case 4 : If we reached this point, the command was not found in any of
+ * the queues.
+ *
+ * We probably reached this point because of an unlikely race condition
+ * between the command completing successfully and the abortion code,
+ * so we won't panic, but we will notify the user in case something really
+ * broke.
+ */
+
+ /* sti();*/
+ wd33c93_execute (instance);
+
+ restore_flags(flags);
+ printk("scsi%d: warning : SCSI command probably completed successfully"
+ " before abortion. ", instance->host_no);
+ return SCSI_ABORT_NOT_RUNNING;
}
-
-
#define MAX_WD33C93_HOSTS 4
#define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *))
#define SETUP_BUFFER_SIZE 200
@@ -1509,322 +1414,305 @@ static char setup_used[MAX_SETUP_STRINGS];
void wd33c93_setup (char *str, int *ints)
{
-int i,x;
-char *p1,*p2;
-
- /* The kernel does some processing of the command-line before calling
- * this function: If it begins with any decimal or hex number arguments,
- * ints[0] = how many numbers found and ints[1] through [n] are the values
- * themselves. str points to where the non-numeric arguments (if any)
- * start: We do our own parsing of those. We construct synthetic 'nosync'
- * keywords out of numeric args (to maintain compatibility with older
- * versions) and then add the rest of the arguments.
- */
-
- p1 = setup_buffer;
- *p1 = '\0';
- if (ints[0]) {
- for (i=0; i<ints[0]; i++) {
- x = vsprintf(p1,"nosync:0x%02x,",&(ints[i+1]));
- p1 += x;
- }
- }
- if (str)
- strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
- setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
- p1 = setup_buffer;
- i = 0;
- while (*p1 && (i < MAX_SETUP_STRINGS)) {
- p2 = strchr(p1, ',');
- if (p2) {
- *p2 = '\0';
- if (p1 != p2)
- setup_strings[i] = p1;
- p1 = p2 + 1;
- i++;
- }
- else {
- setup_strings[i] = p1;
- break;
- }
- }
- for (i=0; i<MAX_SETUP_STRINGS; i++)
- setup_used[i] = 0;
+ int i, x;
+ char *p1, *p2;
+
+ /* The kernel does some processing of the command-line before calling
+ * this function: If it begins with any decimal or hex number arguments,
+ * ints[0] = how many numbers found and ints[1] through [n] are the values
+ * themselves. str points to where the non-numeric arguments (if any)
+ * start: We do our own parsing of those. We construct synthetic 'nosync'
+ * keywords out of numeric args (to maintain compatibility with older
+ * versions) and then add the rest of the arguments.
+ */
+ p1 = setup_buffer;
+ *p1 = '\0';
+ if (ints[0]) {
+ for (i = 0; i < ints[0]; i++) {
+ x = vsprintf(p1, "nosync:0x%02x,", &(ints[i+1]));
+ p1 += x;
+ }
+ }
+ if (str)
+ strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
+ setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
+ p1 = setup_buffer;
+ i = 0;
+ while (*p1 && (i < MAX_SETUP_STRINGS)) {
+ p2 = strchr(p1, ',');
+ if (p2) {
+ *p2 = '\0';
+ if (p1 != p2)
+ setup_strings[i] = p1;
+ p1 = p2 + 1;
+ i++;
+ } else {
+ setup_strings[i] = p1;
+ break;
+ }
+ }
+ for (i = 0; i < MAX_SETUP_STRINGS; i++)
+ setup_used[i] = 0;
}
-
-/* check_setup_strings() returns index if key found, 0 if not
- */
-
+/* check_setup_strings() returns index if key found, 0 if not */
int check_setup_strings(char *key, int *flags, int *val, char *buf)
{
-int x;
-char *cp;
-
- for (x=0; x<MAX_SETUP_STRINGS; x++) {
- if (setup_used[x])
- continue;
- if (!strncmp(setup_strings[x], key, strlen(key)))
- break;
- if (!strncmp(setup_strings[x], "next", strlen("next")))
- return 0;
- }
- if (x == MAX_SETUP_STRINGS)
- return 0;
- setup_used[x] = 1;
- cp = setup_strings[x] + strlen(key);
- *val = -1;
- if (*cp != ':')
- return ++x;
- cp++;
- if ((*cp >= '0') && (*cp <= '9')) {
- *val = simple_strtoul(cp,NULL,0);
- }
- return ++x;
+ int x;
+ char *cp;
+
+ for (x = 0; x < MAX_SETUP_STRINGS; x++) {
+ if (setup_used[x])
+ continue;
+ if (!strncmp(setup_strings[x], key, strlen(key)))
+ break;
+ if (!strncmp(setup_strings[x], "next", strlen("next")))
+ return 0;
+ }
+ if (x == MAX_SETUP_STRINGS)
+ return 0;
+ setup_used[x] = 1;
+ cp = setup_strings[x] + strlen(key);
+ *val = -1;
+ if (*cp != ':')
+ return ++x;
+ cp++;
+ if ((*cp >= '0') && (*cp <= '9'))
+ *val = simple_strtoul(cp, NULL, 0);
+
+ return ++x;
}
-
-
void wd33c93_init (struct Scsi_Host *instance, wd33c93_regs *regs,
- dma_setup_t setup, dma_stop_t stop, int clock_freq)
+ dma_setup_t setup, dma_stop_t stop, int clock_freq)
{
-struct WD33C93_hostdata *hostdata;
-int i;
-int flags;
-int val;
-char buf[32];
-
- hostdata = (struct WD33C93_hostdata *)instance->hostdata;
-
- hostdata->regp = regs;
- hostdata->clock_freq = clock_freq;
- hostdata->dma_setup = setup;
- hostdata->dma_stop = stop;
- hostdata->dma_bounce_buffer = NULL;
- hostdata->dma_bounce_len = 0;
- for (i = 0; i < 8; i++) {
- hostdata->busy[i] = 0;
- hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
- hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
- }
- hostdata->input_Q = NULL;
- hostdata->selecting = NULL;
- hostdata->connected = NULL;
- hostdata->disconnected_Q = NULL;
- hostdata->state = S_UNCONNECTED;
- hostdata->dma = D_DMA_OFF;
- hostdata->level2 = L2_BASIC;
- hostdata->disconnect = DIS_ADAPTIVE;
- hostdata->args = DEBUG_DEFAULTS;
- hostdata->incoming_ptr = 0;
- hostdata->outgoing_len = 0;
- hostdata->default_sx_per = DEFAULT_SX_PER;
- hostdata->no_sync = 0xff; /* sync defaults to off */
+ static int shown = 0;
+ struct WD33C93_hostdata *hostdata = INSTHOSTDATA(instance);
+ int i;
+ int flags;
+ int val;
+ char buf[32];
+
+ hostdata->regp = regs;
+ hostdata->clock_freq = clock_freq;
+ hostdata->dma_setup = setup;
+ hostdata->dma_stop = stop;
+ hostdata->dma_bounce_buffer = NULL;
+ hostdata->dma_bounce_len = 0;
+ for (i = 0; i < 8; i++) {
+ hostdata->busy[i] = 0;
+ hostdata->sync_xfer[i] =
+ calc_sync_xfer(DEFAULT_SX_PER/4, DEFAULT_SX_OFF);
+ hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
+ }
+ hostdata->input_Q = NULL;
+ hostdata->selecting = NULL;
+ hostdata->connected = NULL;
+ hostdata->disconnected_Q = NULL;
+ hostdata->state = S_UNCONNECTED;
+ hostdata->dma = D_DMA_OFF;
+ hostdata->level2 = L2_BASIC;
+ hostdata->disconnect = DIS_ADAPTIVE;
+ hostdata->args = DEBUG_DEFAULTS;
+ hostdata->incoming_ptr = 0;
+ hostdata->outgoing_len = 0;
+ hostdata->default_sx_per = DEFAULT_SX_PER;
+ hostdata->no_sync = 0xff; /* sync defaults to off */
#ifdef PROC_INTERFACE
- hostdata->proc = PR_VERSION|PR_INFO|PR_TOTALS|
- PR_CONNECTED|PR_INPUTQ|PR_DISCQ|
- PR_STOP;
+ hostdata->proc = PR_VERSION|PR_INFO|PR_TOTALS|
+ PR_CONNECTED|PR_INPUTQ|PR_DISCQ|
+ PR_STOP;
- disc_allowed_total = 0;
- disc_taken_total = 0;
+ disc_allowed_total = 0;
+ disc_taken_total = 0;
#endif
-
- if (check_setup_strings("nosync",&flags,&val,buf))
- hostdata->no_sync = val;
-
- if (check_setup_strings("period",&flags,&val,buf))
- hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns;
-
- if (check_setup_strings("disconnect",&flags,&val,buf)) {
- if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
- hostdata->disconnect = val;
- else
- hostdata->disconnect = DIS_ADAPTIVE;
- }
-
- if (check_setup_strings("debug",&flags,&val,buf))
- hostdata->args = val & DB_MASK;
-
- if (check_setup_strings("clock",&flags,&val,buf)) {
- if (val>7 && val<11)
- val = WD33C93_FS_8_10;
- else if (val>11 && val<16)
- val = WD33C93_FS_12_15;
- else if (val>15 && val<21)
- val = WD33C93_FS_16_20;
- else
- val = WD33C93_FS_8_10;
- hostdata->clock_freq = val;
- }
-
- if ((i = check_setup_strings("next",&flags,&val,buf))) {
- while (i)
- setup_used[--i] = 1;
- }
+ if (check_setup_strings("nosync", &flags, &val, buf))
+ hostdata->no_sync = val;
+
+ if (check_setup_strings("period", &flags, &val, buf))
+ hostdata->default_sx_per =
+ sx_table[round_period((unsigned int)val)].period_ns;
+
+ if (check_setup_strings("disconnect", &flags, &val, buf)) {
+ if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
+ hostdata->disconnect = val;
+ else
+ hostdata->disconnect = DIS_ADAPTIVE;
+ }
+
+ if (check_setup_strings("debug", &flags, &val, buf))
+ hostdata->args = val & DB_MASK;
+
+ if (check_setup_strings("clock", &flags, &val, buf)) {
+ if ((val > 7) && (val < 11))
+ val = WD33C93_FS_8_10;
+ else if ((val > 11) && (val < 16))
+ val = WD33C93_FS_12_15;
+ else if ((val > 15) && (val < 21))
+ val = WD33C93_FS_16_20;
+ else
+ val = WD33C93_FS_8_10;
+ hostdata->clock_freq = val;
+ }
+
+ if ((i = check_setup_strings("next", &flags, &val, buf))) {
+ while (i)
+ setup_used[--i] = 1;
+ }
#ifdef PROC_INTERFACE
- if (check_setup_strings("proc",&flags,&val,buf))
- hostdata->proc = val;
+ if (check_setup_strings("proc", &flags, &val, buf))
+ hostdata->proc = val;
#endif
-
- cli();
- reset_wd33c93(instance);
- sti();
-
- printk("wd33c93-%d: chip=%s microcode=%02x\n",instance->host_no,
- (hostdata->chip==C_WD33C93)?"WD33c93":
- (hostdata->chip==C_WD33C93A)?"WD33c93A":
- (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
- hostdata->microcode);
-
-#ifdef DEBUGGING_ON
- printk("wd33c93-%d: setup_strings=",instance->host_no);
- for (i=0; i<MAX_SETUP_STRINGS; i++)
- printk("%s,",setup_strings[i]);
- printk("\n");
- printk("wd33c93-%d: debug_flags = %04x\n",instance->host_no,hostdata->args);
+ cli();
+ reset_wd33c93(instance);
+ sti();
+
+ if(!shown++) {
+ printk("WD93: Driver version %s ", WD33C93_VERSION);
+ printk("compiled on %s at %s\n", __DATE__, __TIME__);
+#if 0
+ printk("wd33c93-%d: setup_strings=", instance->host_no);
+ for (i = 0; i < MAX_SETUP_STRINGS; i++)
+ printk("%s,", setup_strings[i]);
+ printk("\n");
+ printk("wd33c93-%d: debug_flags = %04x\n",
+ instance->host_no, hostdata->args);
#endif
- printk("wd33c93-%d: driver version %s - %s\n",instance->host_no,
- WD33C93_VERSION,WD33C93_DATE);
- printk("wd33c93-%d: compiled on %s at %s\n",instance->host_no,
- __DATE__,__TIME__);
-}
+ }
+ printk("wd33c93-%d: chip=%s microcode=%02x\n", instance->host_no,
+ (hostdata->chip==C_WD33C93) ? "WD33c93" :
+ (hostdata->chip==C_WD33C93A) ? "WD33c93A" :
+ (hostdata->chip==C_WD33C93B) ? "WD33c93B" : "unknown",
+ hostdata->microcode);
+}
int wd33c93_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
{
-
#ifdef PROC_INTERFACE
-
-char *bp;
-char tbuf[128];
-unsigned long flags;
-struct Scsi_Host *instance;
-struct WD33C93_hostdata *hd;
-Scsi_Cmnd *cmd;
-int x,i;
-static int stop = 0;
-
- for (instance=instance_list; instance; instance=instance->next) {
- if (instance->host_no == hn)
- break;
- }
- if (!instance) {
- printk("*** Hmm... Can't find host #%d!\n",hn);
- return (-ESRCH);
- }
- hd = (struct WD33C93_hostdata *)instance->hostdata;
-
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
- * debug
- * disconnect
- * period
- * resync
- * proc
- */
-
- if (in) {
- buf[len] = '\0';
- bp = buf;
- if (!strncmp(bp,"debug:",6)) {
- bp += 6;
- hd->args = simple_strtoul(bp,NULL,0) & DB_MASK;
- }
- else if (!strncmp(bp,"disconnect:",11)) {
- bp += 11;
- x = simple_strtoul(bp,NULL,0);
- if (x < DIS_NEVER || x > DIS_ALWAYS)
- x = DIS_ADAPTIVE;
- hd->disconnect = x;
- }
- else if (!strncmp(bp,"period:",7)) {
- bp += 7;
- x = simple_strtoul(bp,NULL,0);
- hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns;
- }
- else if (!strncmp(bp,"resync:",7)) {
- bp += 7;
- x = simple_strtoul(bp,NULL,0);
- for (i=0; i<7; i++)
- if (x & (1<<i))
- hd->sync_stat[i] = SS_UNSET;
- }
- else if (!strncmp(bp,"proc:",5)) {
- bp += 5;
- hd->proc = simple_strtoul(bp,NULL,0);
- }
- return len;
- }
-
- save_flags(flags);
- cli();
- bp = buf;
- *bp = '\0';
- if (hd->proc & PR_VERSION) {
- sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s",
- WD33C93_VERSION,WD33C93_DATE,__DATE__,__TIME__);
- strcat(bp,tbuf);
- }
- if (hd->proc & PR_INFO) {
- ;
- }
- if (hd->proc & PR_TOTALS) {
- sprintf(tbuf,"\n%ld disc_allowed, %ld disc_taken",
- disc_allowed_total,disc_taken_total);
- strcat(bp,tbuf);
- }
- if (hd->proc & PR_CONNECTED) {
- strcat(bp,"\nconnected: ");
- if (hd->connected) {
- cmd = (Scsi_Cmnd *)hd->connected;
- sprintf(tbuf," %ld-%d:%d(%02x)",
- cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
- strcat(bp,tbuf);
- }
- }
- if (hd->proc & PR_INPUTQ) {
- strcat(bp,"\ninput_Q: ");
- cmd = (Scsi_Cmnd *)hd->input_Q;
- while (cmd) {
- sprintf(tbuf," %ld-%d:%d(%02x)",
- cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
- strcat(bp,tbuf);
- cmd = (Scsi_Cmnd *)cmd->host_scribble;
- }
- }
- if (hd->proc & PR_DISCQ) {
- strcat(bp,"\ndisconnected_Q:");
- cmd = (Scsi_Cmnd *)hd->disconnected_Q;
- while (cmd) {
- sprintf(tbuf," %ld-%d:%d(%02x)",
- cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
- strcat(bp,tbuf);
- cmd = (Scsi_Cmnd *)cmd->host_scribble;
- }
- }
- strcat(bp,"\n");
- restore_flags(flags);
- *start = buf;
- if (stop) {
- stop = 0;
- return 0;
- }
- if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */
- stop = 1;;
- if (hd->proc & PR_STOP) /* stop every other time */
- stop = 1;
- return strlen(bp);
+ char *bp;
+ char tbuf[128];
+ unsigned long flags;
+ struct Scsi_Host *instance;
+ struct WD33C93_hostdata *hd;
+ Scsi_Cmnd *cmd;
+ int x,i;
+ static int stop = 0;
+
+ for (instance = instance_list; instance; instance = instance->next) {
+ if (instance->host_no == hn)
+ break;
+ }
+ if (!instance) {
+ printk("*** Hmm... Can't find host #%d!\n",hn);
+ return (-ESRCH);
+ }
+ hd = (struct WD33C93_hostdata *) instance->hostdata;
+
+ /* If 'in' is TRUE we need to _read_ the proc file. We accept the following
+ * keywords (same format as command-line, but only ONE per read):
+ * debug
+ * disconnect
+ * period
+ * resync
+ * proc
+ */
+ if (in) {
+ buf[len] = '\0';
+ bp = buf;
+ if (!strncmp(bp, "debug:", 6)) {
+ bp += 6;
+ hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+ } else if (!strncmp(bp, "disconnect:", 11)) {
+ bp += 11;
+ x = simple_strtoul(bp, NULL, 0);
+ if ((x < DIS_NEVER) || (x > DIS_ALWAYS))
+ x = DIS_ADAPTIVE;
+ hd->disconnect = x;
+ } else if (!strncmp(bp, "period:", 7)) {
+ bp += 7;
+ x = simple_strtoul(bp, NULL, 0);
+ hd->default_sx_per =
+ sx_table[round_period((unsigned int)x)].period_ns;
+ } else if (!strncmp(bp, "resync:", 7)) {
+ bp += 7;
+ x = simple_strtoul(bp, NULL, 0);
+ for (i = 0; i < 7; i++)
+ if (x & (1<<i))
+ hd->sync_stat[i] = SS_UNSET;
+ } else if (!strncmp(bp, "proc:", 5)) {
+ bp += 5;
+ hd->proc = simple_strtoul(bp, NULL, 0);
+ }
+ return len;
+ }
+
+ save_flags(flags); cli();
+
+ bp = buf;
+ *bp = '\0';
+ if (hd->proc & PR_VERSION) {
+ sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s",
+ WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);
+ strcat(bp, tbuf);
+ }
+ if (hd->proc & PR_INFO) {
+ ;
+ }
+ if (hd->proc & PR_TOTALS) {
+ sprintf(tbuf,"\n%ld disc_allowed, %ld disc_taken",
+ disc_allowed_total, disc_taken_total);
+ strcat(bp, tbuf);
+ }
+ if (hd->proc & PR_CONNECTED) {
+ strcat(bp, "\nconnected: ");
+ if (hd->connected) {
+ cmd = (Scsi_Cmnd *) hd->connected;
+ sprintf(tbuf," %ld-%d:%d(%02x)",
+ cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
+ strcat(bp, tbuf);
+ }
+ }
+ if (hd->proc & PR_INPUTQ) {
+ strcat(bp, "\ninput_Q: ");
+ cmd = (Scsi_Cmnd *) hd->input_Q;
+ while (cmd) {
+ sprintf(tbuf," %ld-%d:%d(%02x)",
+ cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
+ strcat(bp, tbuf);
+ cmd = (Scsi_Cmnd *) cmd->host_scribble;
+ }
+ }
+ if (hd->proc & PR_DISCQ) {
+ strcat(bp, "\ndisconnected_Q:");
+ cmd = (Scsi_Cmnd *) hd->disconnected_Q;
+ while (cmd) {
+ sprintf(tbuf," %ld-%d:%d(%02x)",
+ cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
+ strcat(bp, tbuf);
+ cmd = (Scsi_Cmnd *) cmd->host_scribble;
+ }
+ }
+ strcat(bp, "\n");
+ restore_flags(flags);
+ *start = buf;
+ if (stop) {
+ stop = 0;
+ return 0;
+ }
+ if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */
+ stop = 1;;
+ if (hd->proc & PR_STOP) /* stop every other time */
+ stop = 1;
+ return strlen(bp);
#else /* PROC_INTERFACE */
-
- return 0;
-
+ return 0;
#endif /* PROC_INTERFACE */
-
}
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 123590d5e..82a26cb96 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -17,147 +17,146 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
*/
#ifndef WD33C93_H
#define WD33C93_H
+#include <linux/config.h>
#define uchar unsigned char
-
-/* wd register names */
-#define WD_OWN_ID 0x00
-#define WD_CONTROL 0x01
-#define WD_TIMEOUT_PERIOD 0x02
-#define WD_CDB_1 0x03
-#define WD_CDB_2 0x04
-#define WD_CDB_3 0x05
-#define WD_CDB_4 0x06
-#define WD_CDB_5 0x07
-#define WD_CDB_6 0x08
-#define WD_CDB_7 0x09
-#define WD_CDB_8 0x0a
-#define WD_CDB_9 0x0b
-#define WD_CDB_10 0x0c
-#define WD_CDB_11 0x0d
-#define WD_CDB_12 0x0e
-#define WD_TARGET_LUN 0x0f
-#define WD_COMMAND_PHASE 0x10
-#define WD_SYNCHRONOUS_TRANSFER 0x11
-#define WD_TRANSFER_COUNT_MSB 0x12
-#define WD_TRANSFER_COUNT 0x13
-#define WD_TRANSFER_COUNT_LSB 0x14
-#define WD_DESTINATION_ID 0x15
-#define WD_SOURCE_ID 0x16
-#define WD_SCSI_STATUS 0x17
-#define WD_COMMAND 0x18
-#define WD_DATA 0x19
-#define WD_QUEUE_TAG 0x1a
-#define WD_AUXILIARY_STATUS 0x1f
-
-/* WD commands */
-#define WD_CMD_RESET 0x00
-#define WD_CMD_ABORT 0x01
-#define WD_CMD_ASSERT_ATN 0x02
-#define WD_CMD_NEGATE_ACK 0x03
-#define WD_CMD_DISCONNECT 0x04
-#define WD_CMD_RESELECT 0x05
-#define WD_CMD_SEL_ATN 0x06
-#define WD_CMD_SEL 0x07
-#define WD_CMD_SEL_ATN_XFER 0x08
-#define WD_CMD_SEL_XFER 0x09
-#define WD_CMD_RESEL_RECEIVE 0x0a
-#define WD_CMD_RESEL_SEND 0x0b
-#define WD_CMD_WAIT_SEL_RECEIVE 0x0c
-#define WD_CMD_TRANS_ADDR 0x18
-#define WD_CMD_TRANS_INFO 0x20
-#define WD_CMD_TRANSFER_PAD 0x21
-#define WD_CMD_SBT_MODE 0x80
-
-/* ASR register */
-#define ASR_INT (0x80)
-#define ASR_LCI (0x40)
-#define ASR_BSY (0x20)
-#define ASR_CIP (0x10)
-#define ASR_PE (0x02)
-#define ASR_DBR (0x01)
-
-/* SCSI Bus Phases */
-#define PHS_DATA_OUT 0x00
-#define PHS_DATA_IN 0x01
-#define PHS_COMMAND 0x02
-#define PHS_STATUS 0x03
-#define PHS_MESS_OUT 0x06
-#define PHS_MESS_IN 0x07
+/* WD register names. */
+#define WD_OWN_ID 0x00 /* Own ID register */
+#define WD_CONTROL 0x01 /* Control bits */
+#define WD_TIMEOUT_PERIOD 0x02 /* SCSI timeout period */
+#define WD_CDB_1 0x03 /* SCSI command byte 1 */
+#define WD_CDB_2 0x04 /* SCSI command byte 2 */
+#define WD_CDB_3 0x05 /* SCSI command byte 3 */
+#define WD_CDB_4 0x06 /* SCSI command byte 4 */
+#define WD_CDB_5 0x07 /* SCSI command byte 5 */
+#define WD_CDB_6 0x08 /* SCSI command byte 6 */
+#define WD_CDB_7 0x09 /* SCSI command byte 7 */
+#define WD_CDB_8 0x0a /* SCSI command byte 8 */
+#define WD_CDB_9 0x0b /* SCSI command byte 9 */
+#define WD_CDB_10 0x0c /* SCSI command byte 10 */
+#define WD_CDB_11 0x0d /* SCSI command byte 11 */
+#define WD_CDB_12 0x0e /* SCSI command byte 12 */
+#define WD_TARGET_LUN 0x0f /* Target | Lun */
+#define WD_COMMAND_PHASE 0x10 /* Phase register */
+#define WD_SYNCHRONOUS_TRANSFER 0x11 /* Synchronous indicator */
+#define WD_TRANSFER_COUNT_MSB 0x12 /* Trans cnt, bits<23:16> */
+#define WD_TRANSFER_COUNT 0x13 /* Trans cnt, bits<15:8> */
+#define WD_TRANSFER_COUNT_LSB 0x14 /* Trans cnt, bits<7:0> */
+#define WD_DESTINATION_ID 0x15 /* Dest ID register */
+#define WD_SOURCE_ID 0x16 /* Src ID register */
+#define WD_SCSI_STATUS 0x17 /* Status register */
+#define WD_COMMAND 0x18 /* Command reg */
+#define WD_DATA 0x19 /* Data bus bit reg */
+#define WD_QUEUE_TAG 0x1a /* Queue TAG reg (wd93b) */
+#define WD_AUXILIARY_STATUS 0x1f /* Aux status reg */
+
+/* WD commands. */
+#define WD_CMD_RESET 0x00 /* Reset SCSI bus and wd93x chip */
+#define WD_CMD_ABORT 0x01 /* Stop and abort current action */
+#define WD_CMD_ASSERT_ATN 0x02 /* Assert ATN on SCSI bus */
+#define WD_CMD_NEGATE_ACK 0x03 /* De-assert ACK on SCSI bus */
+#define WD_CMD_DISCONNECT 0x04 /* Causes wd93x to force disconnect */
+#define WD_CMD_RESELECT 0x05 /* Causes wd93x to reselect as targ */
+#define WD_CMD_SEL_ATN 0x06 /* Tells wd93x to select w/ATN assrt */
+#define WD_CMD_SEL 0x07 /* Tells wd93x to select w/o ATN assrt */
+#define WD_CMD_SEL_ATN_XFER 0x08 /* Select w/ATN and transfer data */
+#define WD_CMD_SEL_XFER 0x09 /* Select w/o ATN and transfer data */
+#define WD_CMD_RESEL_RECEIVE 0x0a /* Reselect and into receive mode */
+#define WD_CMD_RESEL_SEND 0x0b /* Reselect and into send mode */
+#define WD_CMD_WAIT_SEL_RECEIVE 0x0c /* Await selection, into receive mode */
+#define WD_CMD_TRANS_ADDR 0x18 /* Address translate */
+#define WD_CMD_TRANS_INFO 0x20 /* Information transfer */
+#define WD_CMD_TRANSFER_PAD 0x21 /* Information pad */
+#define WD_CMD_SBT_MODE 0x80 /* XXX investigate for this comment */
+
+/* ASR (Auxiliary Status) register values. */
+#define ASR_INT (0x80) /* Showing an interrupt */
+#define ASR_LCI (0x40) /* Ignored most recent command */
+#define ASR_BSY (0x20) /* A level II command in progress, therefore busy */
+#define ASR_CIP (0x10) /* A command is in progress */
+#define ASR_PE (0x02) /* Detected a parity error */
+#define ASR_DBR (0x01) /* The data buffer is ready */
+
+/* SCSI Bus Phases. */
+#define PHS_DATA_OUT (0x00)
+#define PHS_DATA_IN (0x01)
+#define PHS_COMMAND (0x02)
+#define PHS_STATUS (0x03)
+#define PHS_MESS_OUT (0x06)
+#define PHS_MESS_IN (0x07)
/* Command Status Register definitions */
- /* reset state interrupts */
-#define CSR_RESET 0x00
-#define CSR_RESET_AF 0x01
+/* reset state interrupts */
+#define CSR_RESET 0x00
+#define CSR_RESET_AF 0x01
- /* successful completion interrupts */
-#define CSR_RESELECT 0x10
-#define CSR_SELECT 0x11
+/* successful completion interrupts */
+#define CSR_RESELECT 0x10
+#define CSR_SELECT 0x11
#define CSR_SEL_XFER_DONE 0x16
#define CSR_XFER_DONE 0x18
- /* paused or aborted interrupts */
-#define CSR_MSGIN 0x20
-#define CSR_SDP 0x21
+/* paused or aborted interrupts */
+#define CSR_MSGIN 0x20
+#define CSR_SDP 0x21
#define CSR_SEL_ABORT 0x22
#define CSR_RESEL_ABORT 0x25
#define CSR_RESEL_ABORT_AM 0x27
-#define CSR_ABORT 0x28
+#define CSR_ABORT 0x28
- /* terminated interrupts */
-#define CSR_INVALID 0x40
+/* terminated interrupts */
+#define CSR_INVALID 0x40
#define CSR_UNEXP_DISC 0x41
-#define CSR_TIMEOUT 0x42
-#define CSR_PARITY 0x43
+#define CSR_TIMEOUT 0x42
+#define CSR_PARITY 0x43
#define CSR_PARITY_ATN 0x44
#define CSR_BAD_STATUS 0x45
-#define CSR_UNEXP 0x48
-
- /* service required interrupts */
-#define CSR_RESEL 0x80
-#define CSR_RESEL_AM 0x81
-#define CSR_DISC 0x85
-#define CSR_SRV_REQ 0x88
-
- /* Own ID/CDB Size register */
-#define OWNID_EAF 0x08
-#define OWNID_EHP 0x10
-#define OWNID_RAF 0x20
-#define OWNID_FS_8 0x00
-#define OWNID_FS_12 0x40
-#define OWNID_FS_16 0x80
-
- /* define these so we don't have to change a2091.c, etc. */
-#define WD33C93_FS_8_10 OWNID_FS_8
-#define WD33C93_FS_12_15 OWNID_FS_12
-#define WD33C93_FS_16_20 OWNID_FS_16
-
- /* Control register */
-#define CTRL_HSP 0x01
-#define CTRL_HA 0x02
-#define CTRL_IDI 0x04
-#define CTRL_EDI 0x08
-#define CTRL_HHP 0x10
-#define CTRL_POLLED 0x00
-#define CTRL_BURST 0x20
-#define CTRL_BUS 0x40
-#define CTRL_DMA 0x80
-
- /* Timeout Period register */
+#define CSR_UNEXP 0x48
+
+/* service required interrupts */
+#define CSR_RESEL 0x80
+#define CSR_RESEL_AM 0x81
+#define CSR_DISC 0x85
+#define CSR_SRV_REQ 0x88
+
+/* Own ID/CDB Size register */
+#define OWNID_EAF 0x08
+#define OWNID_EHP 0x10
+#define OWNID_RAF 0x20
+#define OWNID_FS_8 0x00
+#define OWNID_FS_12 0x40
+#define OWNID_FS_16 0x80
+
+/* define these so we don't have to change a2091.c, etc. */
+#define WD33C93_FS_8_10 OWNID_FS_8
+#define WD33C93_FS_12_15 OWNID_FS_12
+#define WD33C93_FS_16_20 OWNID_FS_16
+
+/* Control register */
+#define CTRL_HSP 0x01
+#define CTRL_HA 0x02
+#define CTRL_IDI 0x04
+#define CTRL_EDI 0x08
+#define CTRL_HHP 0x10
+#define CTRL_POLLED 0x00
+#define CTRL_BURST 0x20
+#define CTRL_BUS 0x40
+#define CTRL_DMA 0x80
+
+/* Timeout Period register */
#define TIMEOUT_PERIOD_VALUE 20 /* 20 = 200 ms */
- /* Synchronous Transfer Register */
+/* Synchronous Transfer Register */
#define STR_FSS 0x80
- /* Destination ID register */
+/* Destination ID register */
#define DSTID_DPD 0x40
#define DATA_OUT_DIR 0
#define DATA_IN_DIR 1
@@ -172,16 +171,17 @@
/* This is what the 3393 chip looks like to us */
typedef struct {
- volatile unsigned char SASR;
- char pad;
- volatile unsigned char SCMD;
+ volatile unsigned char SASR;
+ char pad;
+#ifdef CONFIG_SGI
+ char pad2, pad3; /* HPC is funny like this... */
+#endif
+ volatile unsigned char SCMD;
} wd33c93_regs;
-
typedef int (*dma_setup_t) (Scsi_Cmnd *SCpnt, int dir_in);
typedef void (*dma_stop_t) (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
- int status);
-
+ int status);
#define DEFAULT_SX_PER 500 /* (ns) fairly safe */
#define DEFAULT_SX_OFF 0 /* aka async */
@@ -190,60 +190,59 @@ typedef void (*dma_stop_t) (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
#define OPTIMUM_SX_OFF 12 /* size of wd3393 fifo */
struct sx_period {
- unsigned int period_ns;
- uchar reg_value;
- };
+ unsigned int period_ns;
+ uchar reg_value;
+};
/* FEF: defines for hostdata->dma_buffer_pool */
-
#define BUF_CHIP_ALLOCED 0
#define BUF_SCSI_ALLOCED 1
struct WD33C93_hostdata {
- struct Scsi_Host *next;
- wd33c93_regs *regp;
- uchar clock_freq;
- uchar chip; /* what kind of wd33c93? */
- uchar microcode; /* microcode rev */
- int dma_dir; /* data transfer dir. */
- dma_setup_t dma_setup;
- dma_stop_t dma_stop;
- uchar *dma_bounce_buffer;
- unsigned int dma_bounce_len;
- uchar dma_buffer_pool; /* FEF: buffer from chip_ram? */
- volatile uchar busy[8]; /* index = target, bit = lun */
- volatile Scsi_Cmnd *input_Q; /* commands waiting to be started */
- volatile Scsi_Cmnd *selecting; /* trying to select this command */
- volatile Scsi_Cmnd *connected; /* currently connected command */
- volatile Scsi_Cmnd *disconnected_Q;/* commands waiting for reconnect */
- uchar state; /* what we are currently doing */
- uchar dma; /* current state of DMA (on/off) */
- uchar level2; /* extent to which Level-2 commands are used */
- uchar disconnect; /* disconnect/reselect policy */
- unsigned int args; /* set from command-line argument */
- uchar incoming_msg[8]; /* filled during message_in phase */
- int incoming_ptr; /* mainly used with EXTENDED messages */
- uchar outgoing_msg[8]; /* send this during next message_out */
- int outgoing_len; /* length of outgoing message */
- unsigned int default_sx_per; /* default transfer period for SCSI bus */
- uchar sync_xfer[8]; /* sync_xfer reg settings per target */
- uchar sync_stat[8]; /* status of sync negotiation per target */
- uchar no_sync; /* bitmask: don't do sync on these targets */
+ struct Scsi_Host *next;
+ wd33c93_regs *regp;
+ uchar clock_freq;
+ uchar chip; /* what kind of wd33c93? */
+ uchar microcode; /* microcode rev */
+ int dma_dir; /* data transfer dir. */
+ dma_setup_t dma_setup;
+ dma_stop_t dma_stop;
+ uchar *dma_bounce_buffer;
+ unsigned int dma_bounce_len;
+ uchar dma_buffer_pool; /* FEF: buffer from chip_ram? */
+ volatile uchar busy[8]; /* index = target, bit = lun */
+ volatile Scsi_Cmnd *input_Q; /* commands waiting to be started */
+ volatile Scsi_Cmnd *selecting; /* trying to select this command */
+ volatile Scsi_Cmnd *connected; /* currently connected command */
+ volatile Scsi_Cmnd *disconnected_Q;/* commands waiting for reconnect */
+ uchar state; /* what we are currently doing */
+ uchar dma; /* current state of DMA (on/off) */
+ uchar level2; /* extent to which Level-2 commands are used */
+ uchar disconnect; /* disconnect/reselect policy */
+ unsigned int args; /* set from command-line argument */
+ uchar incoming_msg[8]; /* filled during message_in phase */
+ int incoming_ptr; /* mainly used with EXTENDED messages */
+ uchar outgoing_msg[8]; /* send this during next message_out */
+ int outgoing_len; /* length of outgoing message */
+ unsigned int default_sx_per; /* default transfer period for SCSI bus */
+ uchar sync_xfer[8]; /* sync_xfer reg settings per target */
+ uchar sync_stat[8]; /* status of sync negotiation per target */
+ uchar no_sync; /* bitmask: don't do sync on these targets */
#if 0
- uchar proc; /* bitmask: what's in proc output */
+ uchar proc; /* bitmask: what's in proc output */
#endif
- };
+};
+#define CMDHOSTDATA(cmd) ((struct WD33C93_hostdata *) (cmd)->host->hostdata)
+#define INSTHOSTDATA(inst) ((struct WD33C93_hostdata *) (inst)->hostdata)
/* defines for hostdata->chip */
-
-#define C_WD33C93 0
-#define C_WD33C93A 1
-#define C_WD33C93B 2
-#define C_UNKNOWN_CHIP 100
+#define C_WD33C93 0
+#define C_WD33C93A 1
+#define C_WD33C93B 2
+#define C_UNKNOWN_CHIP 100
/* defines for hostdata->state */
-
#define S_UNCONNECTED 0
#define S_SELECTING 1
#define S_RUNNING_LEVEL2 2
@@ -252,15 +251,18 @@ struct WD33C93_hostdata {
#define S_PRE_CMP_DISC 5
/* defines for hostdata->dma */
-
-#define D_DMA_OFF 0
-#define D_DMA_RUNNING 1
+#define D_DMA_OFF 0
+#define D_DMA_RUNNING 1
/* defines for hostdata->level2 */
/* NOTE: only the first 3 are implemented so far */
-#define L2_NONE 1 /* no combination commands - we get lots of ints */
+/* (The first 8 bits are reserved for compatibility. They function */
+#if 0
#define L2_SELECT 2 /* start with SEL_ATN_XFER, but never resume it */
+#endif
+
+#define L2_NONE 0
#define L2_BASIC 3 /* resume after STATUS ints & RDP messages */
#define L2_DATA 4 /* resume after DATA_IN/OUT ints */
#define L2_MOST 5 /* resume after anything except a RESELECT int */
@@ -268,42 +270,37 @@ struct WD33C93_hostdata {
#define L2_ALL 7 /* always resume */
/* defines for hostdata->disconnect */
-
#define DIS_NEVER 0
#define DIS_ADAPTIVE 1
#define DIS_ALWAYS 2
/* defines for hostdata->args */
-
-#define DB_TEST1 1<<0
-#define DB_TEST2 1<<1
-#define DB_QUEUE_COMMAND 1<<2
-#define DB_EXECUTE 1<<3
-#define DB_INTR 1<<4
-#define DB_TRANSFER 1<<5
-#define DB_MASK 0x3f
+#define DB_TEST1 (1<<0)
+#define DB_TEST2 (1<<1)
+#define DB_QCMD (1<<2)
+#define DB_EXECUTE (1<<3)
+#define DB_INTR (1<<4)
+#define DB_TRANS (1<<5)
+#define DB_MASK (0x3f)
/* defines for hostdata->sync_stat[] */
-
#define SS_UNSET 0
#define SS_FIRST 1
#define SS_WAITING 2
#define SS_SET 3
/* defines for hostdata->proc */
-
-#define PR_VERSION 1<<0
-#define PR_INFO 1<<1
-#define PR_TOTALS 1<<2
-#define PR_CONNECTED 1<<3
-#define PR_INPUTQ 1<<4
-#define PR_DISCQ 1<<5
-#define PR_TEST 1<<6
-#define PR_STOP 1<<7
-
+#define PR_VERSION (1<<0)
+#define PR_INFO (1<<1)
+#define PR_TOTALS (1<<2)
+#define PR_CONNECTED (1<<3)
+#define PR_INPUTQ (1<<4)
+#define PR_DISCQ (1<<5)
+#define PR_TEST (1<<6)
+#define PR_STOP (1<<7)
void wd33c93_init (struct Scsi_Host *instance, wd33c93_regs *regs,
- dma_setup_t setup, dma_stop_t stop, int clock_freq);
+ dma_setup_t setup, dma_stop_t stop, int clock_freq);
int wd33c93_abort (Scsi_Cmnd *cmd);
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
void wd33c93_intr (struct Scsi_Host *instance);
diff --git a/drivers/sgi/Makefile b/drivers/sgi/Makefile
new file mode 100644
index 000000000..40cb89eaa
--- /dev/null
+++ b/drivers/sgi/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+SUB_DIRS :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS) char
+
+L_OBJS :=
+L_TARGET := sgi.a
+
+# Character devices for SGI machines.
+#
+SUB_DIRS += char
+L_OBJS += char/sgichar.o
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/sgi/char/.cvsignore b/drivers/sgi/char/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/sgi/char/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/drivers/sgi/char/Makefile b/drivers/sgi/char/Makefile
new file mode 100644
index 000000000..99440bd60
--- /dev/null
+++ b/drivers/sgi/char/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := sgichar.o
+O_OBJS := newport.o sgicons.o
+
+ifeq ($(CONFIG_SGI_SERIAL),y)
+ O_OBJS += sgiserial.o
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/sgi/char/linux_logo.h b/drivers/sgi/char/linux_logo.h
new file mode 100644
index 000000000..ca041ddde
--- /dev/null
+++ b/drivers/sgi/char/linux_logo.h
@@ -0,0 +1,909 @@
+/* This is a linux logo to be displayed on boot.
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from0x20
+ * (i.e. RGB(linux_logo_red[0],
+ * linux_logo_green[0],
+ * linux_logo_blue[0]) is color0x20)
+ */
+
+#define LINUX_LOGO_COLORS 221
+
+unsigned char linux_logo_red[] = {
+ 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+ 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
+ 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
+ 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
+ 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
+ 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
+ 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+ 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+ 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
+ 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
+ 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
+ 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
+ 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
+ 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
+ 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
+ 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
+ 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
+ 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
+ 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
+ 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
+ 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
+ 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+ 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+ 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+ 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
+ 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
+ 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
+ 0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_green[] = {
+ 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+ 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
+ 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
+ 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
+ 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
+ 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
+ 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+ 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+ 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
+ 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
+ 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
+ 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
+ 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
+ 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
+ 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
+ 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
+ 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
+ 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
+ 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
+ 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
+ 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
+ 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+ 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+ 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+ 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
+ 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
+ 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
+ 0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_blue[] = {
+ 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
+ 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
+ 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
+ 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
+ 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
+ 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
+ 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
+ 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+ 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
+ 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
+ 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
+ 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
+ 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
+ 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
+ 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
+ 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
+ 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
+ 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
+ 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
+ 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
+ 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
+ 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+ 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
+ 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
+ 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
+ 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
+ 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
+ 0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo[] = {
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+ 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
+ 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
+ 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
+ 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
+ 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+ 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
+ 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
+ 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
+ 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
+ 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
+ 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
+ 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
+ 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
+ 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
+ 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
+ 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
+ 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
+ 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
+ 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
+ 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
+ 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
+ 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
+ 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
+ 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
+ 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
+ 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
+ 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
+ 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
+ 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
+ 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
+ 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
+ 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
+ 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
+ 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
+ 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
+ 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
+ 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
+ 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
+ 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
+ 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
+ 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
+ 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
+ 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
+ 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+ 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
+ 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
+ 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
+ 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
+ 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
+ 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
+ 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
+ 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+ 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
+ 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
+ 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
+ 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
+ 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
+ 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
+ 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
+ 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
+ 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
+ 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
+ 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
+ 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
+ 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
+ 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
+ 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
+ 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+ 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
+ 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
+ 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
+ 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
+ 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
+ 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
+ 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
+ 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
+ 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+ 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
+ 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
+ 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
+ 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
+ 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
+ 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
+ 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
+ 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
+ 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
+ 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
+ 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
+ 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
+ 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
+ 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
+ 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
+ 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
+ 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
+ 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
+ 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
+ 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
+ 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
+ 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
+ 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
+ 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
+ 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
+ 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
+ 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
+ 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
+ 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
+ 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
+ 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
+ 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
+ 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
+ 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
+ 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
+ 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
+ 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
+ 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
+ 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
+ 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
+ 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
+ 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
+ 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
+ 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
+ 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
+ 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
+ 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
+ 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
+ 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
+ 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
+ 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
+ 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
+ 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
+ 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
+ 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
+ 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
+ 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
+ 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
+ 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+ 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
+ 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
+ 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
+ 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
+ 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
+ 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
+ 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
+ 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
+ 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
+ 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
+ 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
+ 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
+ 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
+ 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
+ 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
+ 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
+ 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
+ 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
+ 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
+ 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
+ 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
+ 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
+ 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
+ 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
+ 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
+ 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
+ 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
+ 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
+ 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
+ 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
+ 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
+ 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
+ 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
+ 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
+ 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
+ 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
+ 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
+ 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
+ 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
+ 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
+ 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
+ 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
+ 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
+ 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
+ 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
+ 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
+ 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
+ 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
+ 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
+ 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
+ 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
+ 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
+ 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
+ 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
+ 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
+ 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
+ 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
+ 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
+ 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
+ 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
+ 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
+ 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
+ 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
+ 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
+ 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
+ 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
+ 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
+ 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
+ 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
+ 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
+ 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
+ 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
+ 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
+ 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
+ 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
+ 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
+ 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
+ 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
+ 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
+ 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
+ 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
+ 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
+ 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
+ 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
+ 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
+ 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
+ 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
+ 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
+ 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
+ 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
+ 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
+ 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
+ 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
+ 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
+ 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
+ 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
+ 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
+ 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
+ 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
+ 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
+ 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
+ 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
+ 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
+ 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
+ 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
+ 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
+ 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
+ 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
+ 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
+ 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
+ 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
+ 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
+ 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
+ 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
+ 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
+ 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
+ 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
+ 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
+ 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
+ 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
+ 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
+ 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
+ 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
+ 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
+ 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
+ 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
+ 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
+ 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
+ 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
+ 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
+ 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
+ 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
+ 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
+ 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
+ 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
+ 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
+ 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
+ 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
+ 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
+ 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
+ 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
+ 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
+ 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
+ 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
+ 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
+ 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
+ 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
+ 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
+ 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
+ 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
+ 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
+ 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
+ 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
+ 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
+ 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
+ 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
+ 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
+ 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
+ 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
+ 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
+ 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
+ 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
+ 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
+ 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
+ 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
+ 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
+ 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
+ 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
+ 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
+ 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
+ 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
+ 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
+ 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
+ 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
+ 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
+ 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
+ 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
+ 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
+ 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
+ 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
+ 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
+ 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
+ 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+ 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
+ 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
+ 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
+ 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
+ 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
+ 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
+ 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
+ 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
+ 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
+ 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
+ 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
+ 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
+ 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
+ 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
+ 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
+ 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
+ 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
+ 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
+ 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
+ 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
+ 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
+ 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
+ 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
+ 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
+ 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
+ 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
+ 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
+ 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
+ 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
+ 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
+ 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
+ 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
+ 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
+ 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
+ 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+ 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
+ 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
+ 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
+ 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
+ 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
+ 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
+ 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
+ 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+ 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
+ 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
+ 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
+ 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
+ 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
+ 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
+ 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
+ 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+ 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
+ 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
+ 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
+ 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
+ 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
+ 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
+ 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
+ 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
+ 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
+ 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
+ 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
+ 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
+ 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
+ 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
+ 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
+ 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
+ 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
+ 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
+ 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
+ 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
+ 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
+ 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
+ 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
+ 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
+ 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
+ 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
+ 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
+ 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
+ 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
+ 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
+ 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
+ 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
+ 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
+ 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
+ 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
+ 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
+ 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
+ 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
+ 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
+ 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
+ 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
+ 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
+ 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
+ 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
+ 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
+ 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
+ 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
+ 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
+ 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
+ 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
+ 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
+ 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+ 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
+ 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
+ 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
+ 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
+ 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
+ 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
+ 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
+ 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
+ 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
+ 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
+ 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
+ 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
+ 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
+ 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
+ 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
+ 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
+ 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
+ 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
+ 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
+ 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
+ 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
+ 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
+ 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+ 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
+ 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
+ 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
+ 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
+ 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
+ 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
+ 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
+ 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
+ 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+ 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
+ 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
+ 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
+ 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
+ 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
+ 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
+ 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
+ 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
+ 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
+ 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
+ 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
+ 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
+ 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
+ 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
+ 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
+ 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
+ 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
+ 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
+ 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
+ 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
+ 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
+ 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
+ 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
+ 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
+ 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
+ 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
+ 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
+ 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
+ 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
+ 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
+ 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
+ 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
+ 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
+ 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
+ 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
+ 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
+ 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
+ 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
+ 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
+ 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
+ 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
+ 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
+ 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
+ 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
+ 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
+ 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
+ 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
+ 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
+ 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
+ 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
+ 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
+ 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
+ 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
+ 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
+ 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
+ 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
+ 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
+ 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
+ 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
+ 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
+ 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
+ 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
+ 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
+ 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
+ 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
+ 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
+ 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
+ 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
+ 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
+ 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
+ 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
+ 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
+ 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
+ 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
+ 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
+ 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
+ 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
+ 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
+ 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
+ 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
+ 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
+ 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
+ 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
+ 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
+ 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
+ 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
+ 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
+ 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
+ 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
+ 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
+ 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
+ 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
+ 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
+ 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
+ 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
+ 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
+ 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
+ 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
+ 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
+ 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
+ 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
+ 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
+ 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
+ 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
+ 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
+ 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
+ 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
+ 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
+ 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
+ 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
+ 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
+ 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
+ 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
+ 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
+ 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
+ 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
+ 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
+ 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
+ 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
+ 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
+ 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
+ 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
+ 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
+ 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
+ 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
+ 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
+ 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
+ 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
+ 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
+ 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
+ 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
+ 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
+ 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
+ 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
+ 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
+ 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
+ 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
+ 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
+ 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
+ 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
+ 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
+ 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
+ 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
+ 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
+ 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
+ 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
+ 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
+ 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
+ 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
+ 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
+ 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
+ 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
+ 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
+ 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
+ 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
+ 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
+ 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
+ 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
+ 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
+ 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
+ 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
+ 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
+ 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
+ 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
+ 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
+ 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
+ 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
+ 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
+ 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
+ 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
+ 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
+ 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
+ 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
+ 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
+ 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
+ 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
+ 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
+ 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
+ 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
+ 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
+};
+
diff --git a/drivers/sgi/char/newport.c b/drivers/sgi/char/newport.c
new file mode 100644
index 000000000..103b43c7f
--- /dev/null
+++ b/drivers/sgi/char/newport.c
@@ -0,0 +1,940 @@
+/* $Id: newport.c,v 1.7 1996/07/29 11:10:21 dm Exp $
+ * newport.c: Newport graphics console code for the SGI.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/version.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/sgialib.h>
+#include <asm/ptrace.h>
+
+#include "../../char/kbd_kern.h"
+#include "../../char/vt_kern.h"
+#include "../../char/consolemap.h"
+#include "../../char/selection.h"
+#include "../../char/console_struct.h"
+
+#include "newport.h"
+
+#if 0
+#include "linux_logo.h"
+#endif
+
+#define cmapsz 8192
+#define CHAR_HEIGHT 16
+
+#define BMASK(c) (c << 24)
+
+#define RENDER(regs, cp) do { \
+(regs)->go.zpat = BMASK((cp)[0x0]); (regs)->go.zpat = BMASK((cp)[0x1]); \
+(regs)->go.zpat = BMASK((cp)[0x2]); (regs)->go.zpat = BMASK((cp)[0x3]); \
+(regs)->go.zpat = BMASK((cp)[0x4]); (regs)->go.zpat = BMASK((cp)[0x5]); \
+(regs)->go.zpat = BMASK((cp)[0x6]); (regs)->go.zpat = BMASK((cp)[0x7]); \
+(regs)->go.zpat = BMASK((cp)[0x8]); (regs)->go.zpat = BMASK((cp)[0x9]); \
+(regs)->go.zpat = BMASK((cp)[0xa]); (regs)->go.zpat = BMASK((cp)[0xb]); \
+(regs)->go.zpat = BMASK((cp)[0xc]); (regs)->go.zpat = BMASK((cp)[0xd]); \
+(regs)->go.zpat = BMASK((cp)[0xe]); (regs)->go.zpat = BMASK((cp)[0xf]); \
+} while(0)
+
+#define REVERSE_RENDER(regs, cp) do { \
+(regs)->go.zpat = BMASK((~(cp)[0x0])); (regs)->go.zpat = BMASK((~(cp)[0x1])); \
+(regs)->go.zpat = BMASK((~(cp)[0x2])); (regs)->go.zpat = BMASK((~(cp)[0x3])); \
+(regs)->go.zpat = BMASK((~(cp)[0x4])); (regs)->go.zpat = BMASK((~(cp)[0x5])); \
+(regs)->go.zpat = BMASK((~(cp)[0x6])); (regs)->go.zpat = BMASK((~(cp)[0x7])); \
+(regs)->go.zpat = BMASK((~(cp)[0x8])); (regs)->go.zpat = BMASK((~(cp)[0x9])); \
+(regs)->go.zpat = BMASK((~(cp)[0xa])); (regs)->go.zpat = BMASK((~(cp)[0xb])); \
+(regs)->go.zpat = BMASK((~(cp)[0xc])); (regs)->go.zpat = BMASK((~(cp)[0xd])); \
+(regs)->go.zpat = BMASK((~(cp)[0xe])); (regs)->go.zpat = BMASK((~(cp)[0xf])); \
+} while(0)
+
+extern unsigned char vga_font[];
+
+extern unsigned char video_type;
+
+struct newport_regs *npregs;
+
+#define TESTVAL 0xdeadbeef
+#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11)
+
+static int newport_probe(void)
+{
+ struct newport_regs *p = npregs;
+
+ p->cset.cfg = NPORT_CFG_GD0;
+
+ if(newport_wait()) {
+ prom_printf("whoops, timeout, no NEWPORT there?");
+ return 0;
+ }
+
+ p->set.xsti = TESTVAL;
+ if(p->set.fxstart.i != XSTI_TO_FXSTART(TESTVAL)) {
+ prom_printf("newport_probe: read back wrong value ;-(\n");
+ return 0;
+ }
+ return 1;
+}
+
+static inline void newport_disable_video(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO)));
+}
+
+static inline void newport_enable_video(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO));
+}
+
+static inline void newport_disable_cursor(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP)));
+}
+
+#if 0
+static inline void newport_enable_cursor(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
+}
+#endif
+
+extern int default_red[16], default_grn[16], default_blu[16];
+
+
+static inline void newport_init_cmap(void)
+{
+ unsigned short i;
+
+ for(i = 0; i < 16; i++) {
+ newport_bfwait();
+ newport_cmap_setaddr(npregs, color_table[i]);
+ newport_cmap_setrgb(npregs,
+ default_red[i],
+ default_grn[i],
+ default_blu[i]);
+ }
+}
+
+#if 0
+static inline void newport_init_cursor(void)
+{
+ unsigned char cursor[256];
+ unsigned short *cookie;
+ int i;
+
+ for(i = 0; i < 256; i++)
+ cursor[i] = 0x0;
+ for(i = 211; i < 256; i+=4) {
+ cursor[i] = 0xff;
+#if 0
+ cursor[(i + 128) << 2] = 0xff;
+ cursor[((i + 128) << 2) + 1] = 0xff;
+#endif
+ }
+
+ /* Load the SRAM on the VC2 for this new GLYPH. */
+ cookie = (unsigned short *) cursor;
+ newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR);
+ npregs->set.dmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL);
+ for(i = 0; i < 128; i++) {
+ newport_bfwait();
+ npregs->set.ddata0.hwords.s1 = *cookie++;
+ }
+
+ /* Place the cursor at origin. */
+ newport_vc2_set(npregs, VC2_IREG_CURSX, 0);
+ newport_vc2_set(npregs, VC2_IREG_CURSY, 0);
+ newport_enable_cursor();
+}
+#endif
+
+static inline void newport_clear_screen(void)
+{
+ newport_wait();
+ npregs->set.wmask = 0xffffffff;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+ NPORT_DMODE0_STOPY);
+ npregs->set.ci = 0;
+ npregs->set.xysti = 0;
+ npregs->go.xyei = (((1280 + 63) << 16)|(1024));
+ newport_bfwait();
+}
+
+static inline void newport_render_version(void)
+{
+#if 0
+ unsigned short *ush;
+ int currcons = 0;
+ char *p;
+
+ ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20;
+ for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) {
+ *ush = (attr << 8) + *p;
+ newport_blitc (*ush, (unsigned long) ush);
+ }
+#endif
+}
+
+#if 0
+static inline void newport_render_logo(void)
+{
+ int i, xpos, ypos;
+ unsigned char *bmap;
+
+ xpos = 8;
+ ypos = 18;
+
+ newport_wait();
+ npregs->set.ci = 9;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+
+ for(i = 0; i < 80; i+=8) {
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xysti = ((xpos + i) << 16) | ypos;
+ npregs->set.xyei = (((xpos + i) + 7) << 16);
+ newport_wait();
+
+ bmap = linux_logo + (i * 80);
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap);
+ }
+ prom_getchar();
+ prom_imode();
+}
+#endif
+
+void newport_init(void)
+{
+ npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000);
+
+ can_do_color = 1;
+ if(!newport_probe()) {
+ prom_printf("newport_init: something wrong, cannot find card\n");
+ prom_printf("press a key to reset\n");
+ prom_getchar();
+ }
+
+ newport_wait();
+ newport_enable_video();
+
+ /* Init the cursor disappear. */
+ newport_wait();
+#if 0
+ newport_init_cursor();
+#else
+ newport_disable_cursor();
+#endif
+
+ newport_init_cmap();
+
+ /* Clear the screen. */
+ newport_clear_screen();
+ newport_render_version();
+#if 0
+ newport_render_logo();
+#endif
+
+ video_type = VIDEO_TYPE_SGI;
+}
+
+static inline void newport_render_background(int xpos, int ypos, int ci)
+{
+ newport_wait();
+ npregs->set.wmask = 0xffffffff;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+ NPORT_DMODE0_STOPY);
+ npregs->set.ci = ci;
+ npregs->set.xysti = (xpos << 16) | ypos;
+ npregs->go.xyei = ((xpos + 7) << 16) | (ypos + 15);
+}
+
+void __set_origin(unsigned short offset)
+{
+ /* maybe this works... */
+ __origin = offset;
+}
+
+static int cursor_pos = -1;
+
+void hide_cursor(void)
+{
+ int xpos, ypos, idx;
+ unsigned long flags;
+
+ if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ return;
+ save_flags(flags); cli();
+
+ idx = cursor_pos;
+ if(idx == -1) {
+ restore_flags(flags);
+ return;
+ }
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+ newport_render_background(xpos, ypos, 0);
+ restore_flags(flags);
+}
+
+void set_cursor(int currcons)
+{
+ int xpos, ypos, idx, oldpos;
+ unsigned short *sp, *osp, cattr;
+ unsigned long flags;
+ unsigned char *p;
+
+ if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
+ return;
+
+ if (__real_origin != __origin)
+ __set_origin(__real_origin);
+
+ save_flags(flags); cli();
+
+ idx = (pos - video_mem_base) >> 1;
+ sp = (unsigned short *) pos;
+ oldpos = cursor_pos;
+ cursor_pos = idx;
+ if(!deccm) {
+ hide_cursor();
+ restore_flags(flags);
+ return;
+ }
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+ if(oldpos != -1) {
+ int oxpos, oypos;
+
+ /* Restore old location. */
+ osp = (unsigned short *) ((oldpos << 1) + video_mem_base);
+ oxpos = 8 + ((oldpos % video_num_columns) << 3);
+ oypos = 18 + ((oldpos / video_num_columns) << 4);
+ cattr = *osp;
+ newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12);
+ p = &vga_font[(cattr & 0xff) << 4];
+ newport_wait();
+ npregs->set.ci = (cattr & 0x0f00) >> 8;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+ npregs->set.xysti = (oxpos << 16) | oypos;
+ npregs->set.xyei = ((oxpos + 7) << 16);
+ newport_wait();
+ RENDER(npregs, p);
+ }
+ cattr = *sp;
+ newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12);
+ p = &vga_font[(cattr & 0xff) << 4];
+ newport_wait();
+ npregs->set.ci = (cattr & 0x0f00) >> 8;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+ npregs->set.xysti = (xpos << 16) | ypos;
+ npregs->set.xyei = ((xpos + 7) << 16);
+ newport_wait();
+ REVERSE_RENDER(npregs, p);
+}
+
+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;
+ 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);
+ has_wrapped = 0;
+}
+
+int set_get_font(char * arg, int set, int ch512)
+{
+ int error, i, line;
+
+ if (!arg)
+ return -EINVAL;
+ error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg,
+ ch512 ? 2* cmapsz : cmapsz);
+ if (error)
+ return error;
+
+ /* download the current font */
+ if (!set) {
+ memset (arg, 0, cmapsz);
+ for (i = 0; i < 256; i++) {
+ for (line = 0; line < CHAR_HEIGHT; line++)
+ put_user (vga_font [i], arg+(i*32+line));
+ }
+ return 0;
+ }
+
+ /* set the font */
+ for (i = 0; i < 256; i++) {
+ for (line = 0; line < CHAR_HEIGHT; line++) {
+ vga_font [i*CHAR_HEIGHT + line] =
+ (get_user (arg + (i * 32 + line)));
+ }
+ }
+ return 0;
+}
+
+int con_adjust_height(unsigned long fontheight)
+{
+ return -EINVAL;
+}
+
+int set_get_cmap(unsigned char * arg, int set)
+{
+ unsigned short ent;
+ int i;
+
+ i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
+ if (i)
+ return i;
+
+ for (i=0; i<16; i++) {
+ if (set) {
+ default_red[i] = get_user(arg++) ;
+ default_grn[i] = get_user(arg++) ;
+ default_blu[i] = get_user(arg++) ;
+ } else {
+ put_user (default_red[i], arg++) ;
+ put_user (default_grn[i], arg++) ;
+ put_user (default_blu[i], arg++) ;
+ }
+ }
+ 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];
+ }
+ }
+ }
+ if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ return 0;
+ for(ent = 0; ent < 16; ent++) {
+ newport_bfwait();
+ newport_cmap_setaddr(npregs, ent);
+ newport_cmap_setrgb(npregs,
+ default_red[ent],
+ default_grn[ent],
+ default_blu[ent]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * dummy routines for the VESA blanking code, which is VGA only,
+ * so we don't have to carry that stuff around for the Sparc...
+ */
+void vesa_blank(void) { }
+void vesa_unblank(void) { }
+void set_vesa_blanking(const unsigned long arg) { }
+void vesa_powerdown(void) { }
+void set_palette (void) { }
+
+void
+newport_blitc(unsigned short charattr, unsigned long addr)
+{
+ int idx, xpos, ypos;
+ unsigned char *p;
+
+ idx = (addr - (video_mem_base + (__origin<<1))) >> 1;
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+
+ p = &vga_font[(charattr & 0xff) << 4];
+ charattr = (charattr >> 8) & 0xff;
+
+ newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4);
+
+ /* Set the color and drawing mode. */
+ newport_wait();
+ npregs->set.ci = charattr & 0xf;
+ npregs->set.dmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xysti = (xpos << 16) | ypos;
+ npregs->set.xyei = ((xpos + 7) << 16);
+ newport_wait();
+
+ /* Go, baby, go... */
+ RENDER(npregs, p);
+}
+
+void memsetw(void * s, unsigned short c, unsigned int count)
+{
+ unsigned short * addr = (unsigned short *) s;
+
+ count /= 2;
+ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
+ while (count) {
+ count--;
+ *addr++ = c;
+ }
+ return;
+ }
+ if ((unsigned long) addr + count > video_mem_term ||
+ (unsigned long) addr < video_mem_base) {
+ if ((unsigned long) addr + count <= video_mem_term ||
+ (unsigned long) addr > video_mem_base) {
+ while (count) {
+ count--;
+ *addr++ = c;
+ }
+ return;
+ } else {
+ while (count) {
+ count--;
+ scr_writew(c, addr++);
+ }
+ }
+ } else {
+ while (count) {
+ count--;
+ if (*addr != c) {
+ newport_blitc(c, (unsigned long)addr);
+ *addr++ = c;
+ } else
+ addr++;
+ }
+ }
+}
+
+void memcpyw(unsigned short *to, unsigned short *from, unsigned int count)
+{
+ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
+ memcpy(to, from, count);
+ return;
+ }
+ if ((unsigned long) to + count > video_mem_term ||
+ (unsigned long) to < video_mem_base) {
+ if ((unsigned long) to + count <= video_mem_term ||
+ (unsigned long) to > video_mem_base)
+ memcpy(to, from, count);
+ else {
+ count /= 2;
+ while (count) {
+ count--;
+ scr_writew(scr_readw(from++), to++);
+ }
+ }
+ } else {
+ count /= 2;
+ while (count) {
+ count--;
+ if (*to != *from) {
+ newport_blitc(*from, (unsigned long)to);
+ *to++ = *from++;
+ } else {
+ from++;
+ to++;
+ }
+ }
+ }
+}
+
+unsigned char vga_font[cmapsz] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
+0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
+0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
+0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
+0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
+0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
+0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
+0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
+0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
+0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
+0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
+0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
+0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
+0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
+0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
+0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
+0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
+0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
+0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
+0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
+0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
+0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
+0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
+0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
+0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
+0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
+0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
+0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
+0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
+0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
+0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/drivers/sgi/char/newport.h b/drivers/sgi/char/newport.h
new file mode 100644
index 000000000..75ea628c2
--- /dev/null
+++ b/drivers/sgi/char/newport.h
@@ -0,0 +1,409 @@
+/* $Id: newport.h,v 1.2 1996/06/10 16:38:34 dm Exp $
+ * newport.h: Defines and register layout for NEWPORT graphics
+ * hardware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _SGI_NEWPORT_H
+#define _SGI_NEWPORT_H
+
+
+typedef volatile unsigned long npireg_t;
+
+union npfloat {
+ volatile float f;
+ npireg_t i;
+};
+
+typedef union npfloat npfreg_t;
+
+union np_dcb {
+ npireg_t all;
+ struct { volatile unsigned short s0, s1; } hwords;
+ struct { volatile unsigned char b0, b1, b2, b3; } bytes;
+};
+
+struct newport_rexregs {
+ npireg_t dmode1; /* GL extra mode bits */
+#define NPORT_DMODE1_PMASK 0x00000007
+#define NPORT_DMODE1_NOPLANES 0x00000000
+#define NPORT_DMODE1_RGBPLANES 0x00000001
+#define NPORT_DMODE1_RGBAPLANES 0x00000002
+#define NPORT_DMODE1_OLPLANES 0x00000004
+#define NPORT_DMODE1_PUPPLANES 0x00000005
+#define NPORT_DMODE1_CIDPLANES 0x00000006
+#define NPORT_DMODE1_DDMASK 0x00000018
+#define NPORT_DMODE1_DD4 0x00000000
+#define NPORT_DMODE1_DD8 0x00000008
+#define NPORT_DMODE1_DD12 0x00000010
+#define NPORT_DMODE1_DD24 0x00000018
+#define NPORT_DMODE1_DSRC 0x00000020
+#define NPORT_DMODE1_YFLIP 0x00000040
+#define NPORT_DMODE1_RWPCKD 0x00000080
+#define NPORT_DMODE1_HDMASK 0x00000300
+#define NPORT_DMODE1_HD4 0x00000000
+#define NPORT_DMODE1_HD8 0x00000100
+#define NPORT_DMODE1_HD12 0x00000200
+#define NPORT_DMODE1_HD32 0x00000300
+#define NPORT_DMODE1_RWDBL 0x00000400
+#define NPORT_DMODE1_ESWAP 0x00000800 /* Endian swap */
+#define NPORT_DMODE1_CCMASK 0x00007000
+#define NPORT_DMODE1_CCLT 0x00001000
+#define NPORT_DMODE1_CCEQ 0x00002000
+#define NPORT_DMODE1_CCGT 0x00004000
+#define NPORT_DMODE1_RGBMD 0x00008000
+#define NPORT_DMODE1_DENAB 0x00010000 /* Dither enable */
+#define NPORT_DMODE1_FCLR 0x00020000 /* Fast clear */
+#define NPORT_DMODE1_BENAB 0x00040000 /* Blend enable */
+#define NPORT_DMODE1_SFMASK 0x00380000
+#define NPORT_DMODE1_SF0 0x00000000
+#define NPORT_DMODE1_SF1 0x00080000
+#define NPORT_DMODE1_SFDC 0x00100000
+#define NPORT_DMODE1_SFMDC 0x00180000
+#define NPORT_DMODE1_SFSA 0x00200000
+#define NPORT_DMODE1_SFMSA 0x00280000
+#define NPORT_DMODE1_DFMASK 0x01c00000
+#define NPORT_DMODE1_DF0 0x00000000
+#define NPORT_DMODE1_DF1 0x00400000
+#define NPORT_DMODE1_DFSC 0x00800000
+#define NPORT_DMODE1_DFMSC 0x00c00000
+#define NPORT_DMODE1_DFSA 0x01000000
+#define NPORT_DMODE1_DFMSA 0x01400000
+#define NPORT_DMODE1_BBENAB 0x02000000 /* Back blend enable */
+#define NPORT_DMODE1_PFENAB 0x04000000 /* Pre-fetch enable */
+#define NPORT_DMODE1_ABLEND 0x08000000 /* Alpha blend */
+#define NPORT_DMODE1_LOMASK 0xf0000000
+#define NPORT_DMODE1_LOZERO 0x00000000
+#define NPORT_DMODE1_LOAND 0x10000000
+#define NPORT_DMODE1_LOANDR 0x20000000
+#define NPORT_DMODE1_LOSRC 0x30000000
+#define NPORT_DMODE1_LOANDI 0x40000000
+#define NPORT_DMODE1_LODST 0x50000000
+#define NPORT_DMODE1_LOXOR 0x60000000
+#define NPORT_DMODE1_LOOR 0x70000000
+#define NPORT_DMODE1_LONOR 0x80000000
+#define NPORT_DMODE1_LOXNOR 0x90000000
+#define NPORT_DMODE1_LONDST 0xa0000000
+#define NPORT_DMODE1_LOORR 0xb0000000
+#define NPORT_DMODE1_LONSRC 0xc0000000
+#define NPORT_DMODE1_LOORI 0xd0000000
+#define NPORT_DMODE1_LONAND 0xe0000000
+#define NPORT_DMODE1_LOONE 0xf0000000
+
+ npireg_t dmode0; /* REX command register */
+
+ /* These bits define the graphics opcode being performed. */
+#define NPORT_DMODE0_OPMASK 0x00000003 /* Opcode mask */
+#define NPORT_DMODE0_NOP 0x00000000 /* No operation */
+#define NPORT_DMODE0_RD 0x00000001 /* Read operation */
+#define NPORT_DMODE0_DRAW 0x00000002 /* Draw operation */
+#define NPORT_DMODE0_S2S 0x00000003 /* Screen to screen operation */
+
+ /* The following decide what addressing mode(s) are to be used */
+#define NPORT_DMODE0_AMMASK 0x0000001c /* Address mode mask */
+#define NPORT_DMODE0_SPAN 0x00000000 /* Spanning address mode */
+#define NPORT_DMODE0_BLOCK 0x00000004 /* Block address mode */
+#define NPORT_DMODE0_ILINE 0x00000008 /* Iline address mode */
+#define NPORT_DMODE0_FLINE 0x0000000c /* Fline address mode */
+#define NPORT_DMODE0_ALINE 0x00000010 /* Aline address mode */
+#define NPORT_DMODE0_TLINE 0x00000014 /* Tline address mode */
+#define NPORT_DMODE0_BLINE 0x00000018 /* Bline address mode */
+
+ /* And now some misc. operation control bits. */
+#define NPORT_DMODE0_DOSETUP 0x00000020
+#define NPORT_DMODE0_CHOST 0x00000040
+#define NPORT_DMODE0_AHOST 0x00000080
+#define NPORT_DMODE0_STOPX 0x00000100
+#define NPORT_DMODE0_STOPY 0x00000200
+#define NPORT_DMODE0_SK1ST 0x00000400
+#define NPORT_DMODE0_SKLST 0x00000800
+#define NPORT_DMODE0_ZPENAB 0x00001000
+#define NPORT_DMODE0_LISPENAB 0x00002000
+#define NPORT_DMODE0_LISLST 0x00004000
+#define NPORT_DMODE0_L32 0x00008000
+#define NPORT_DMODE0_ZOPQ 0x00010000
+#define NPORT_DMODE0_LISOPQ 0x00020000
+#define NPORT_DMODE0_SHADE 0x00040000
+#define NPORT_DMODE0_LRONLY 0x00080000
+#define NPORT_DMODE0_XYOFF 0x00100000
+#define NPORT_DMODE0_CLAMP 0x00200000
+#define NPORT_DMODE0_ENDPF 0x00400000
+#define NPORT_DMODE0_YSTR 0x00800000
+
+ npireg_t lismode; /* Mode for line stipple ops */
+ npireg_t lispat; /* Pattern for line stipple ops */
+ npireg_t lispsave; /* Backup save pattern */
+ npireg_t zpat; /* Pixel zpattern */
+ npireg_t colbk; /* Background color */
+ npireg_t colvram; /* Clear color for fast vram */
+ npireg_t aref; /* Reference value for afunctions */
+ unsigned long _unused0;
+ npireg_t scmskx0; /* Window GL relative screen mask 0 */
+ npireg_t scmsky0; /* Window GL relative screen mask 0 */
+ npireg_t xsetup;
+ npireg_t xzpenab;
+ npireg_t xlisrestore;
+ npireg_t xlissave;
+
+ unsigned long _unused1[0x30];
+
+ npfreg_t fxstart;
+ npfreg_t fystart;
+ npfreg_t fxend;
+ npfreg_t fyend;
+ npireg_t xsv;
+ npireg_t xymv;
+ npfreg_t brd;
+ npfreg_t brs1;
+ npireg_t broinc1;
+ volatile int brinc2;
+ npireg_t bre1;
+ npireg_t bre2;
+ npireg_t aw0;
+ npireg_t aw1;
+ npfreg_t xstf;
+ npfreg_t ystf;
+ npfreg_t xef;
+ npfreg_t yef;
+ npireg_t xsti;
+ npfreg_t xef1;
+ npireg_t xysti;
+ npireg_t xyei;
+ npireg_t xstei;
+
+ unsigned long _unused2[0x29];
+
+ npfreg_t cred;
+ npfreg_t calpha;
+ npfreg_t cgreen;
+ npfreg_t cblue;
+ npfreg_t slred;
+ npfreg_t slalpha;
+ npfreg_t slgreen;
+ npfreg_t slblue;
+ npireg_t wmask;
+ npireg_t ci;
+ npfreg_t cx;
+ npfreg_t sl1;
+ npireg_t hrw0;
+ npireg_t hrw1;
+ npireg_t dmode;
+#define NPORT_DMODE_WMASK 0x00000003
+#define NPORT_DMODE_W4 0x00000000
+#define NPORT_DMODE_W1 0x00000001
+#define NPORT_DMODE_W2 0x00000002
+#define NPORT_DMODE_W3 0x00000003
+#define NPORT_DMODE_EDPACK 0x00000004
+#define NPORT_DMODE_ECINC 0x00000008
+#define NPORT_DMODE_CMASK 0x00000070
+#define NPORT_DMODE_AMASK 0x00000780
+#define NPORT_DMODE_AVC2 0x00000000
+#define NPORT_DMODE_ACMALL 0x00000080
+#define NPORT_DMODE_ACM0 0x00000100
+#define NPORT_DMODE_ACM1 0x00000180
+#define NPORT_DMODE_AXMALL 0x00000200
+#define NPORT_DMODE_AXM0 0x00000280
+#define NPORT_DMODE_AXM1 0x00000300
+#define NPORT_DMODE_ABT 0x00000380
+#define NPORT_DMODE_AVCC1 0x00000400
+#define NPORT_DMODE_AVAB1 0x00000480
+#define NPORT_DMODE_ALG3V0 0x00000500
+#define NPORT_DMODE_A1562 0x00000580
+#define NPORT_DMODE_ESACK 0x00000800
+#define NPORT_DMODE_EASACK 0x00001000
+#define NPORT_DMODE_CWMASK 0x0003e000
+#define NPORT_DMODE_CHMASK 0x007c0000
+#define NPORT_DMODE_CSMASK 0x0f800000
+#define NPORT_DMODE_SENDIAN 0x10000000
+
+ unsigned long _unused3;
+
+ union np_dcb ddata0;
+ npireg_t ddata1;
+};
+
+struct newport_cregs {
+ npireg_t smskx1;
+ npireg_t smsky1;
+ npireg_t smskx2;
+ npireg_t smsky2;
+ npireg_t smskx3;
+ npireg_t smsky3;
+ npireg_t smskx4;
+ npireg_t smsky4;
+ npireg_t tscan;
+ npireg_t win;
+ npireg_t cmode;
+#define NPORT_CMODE_SM0 0x00000001
+#define NPORT_CMODE_SM1 0x00000002
+#define NPORT_CMODE_SM2 0x00000004
+#define NPORT_CMODE_SM3 0x00000008
+#define NPORT_CMODE_SM4 0x00000010
+#define NPORT_CMODE_CMSK 0x00001e00
+
+ unsigned long _unused0;
+ unsigned long cfg;
+#define NPORT_CFG_G32MD 0x00000001
+#define NPORT_CFG_BWIDTH 0x00000002
+#define NPORT_CFG_ERCVR 0x00000004
+#define NPORT_CFG_BDMSK 0x00000078
+#define NPORT_CFG_GDMSK 0x00000f80
+#define NPORT_CFG_GD0 0x00000080
+#define NPORT_CFG_GD1 0x00000100
+#define NPORT_CFG_GD2 0x00000200
+#define NPORT_CFG_GD3 0x00000400
+#define NPORT_CFG_GD4 0x00000800
+#define NPORT_CFG_GFAINT 0x00001000
+#define NPORT_CFG_TOMSK 0x0000e000
+#define NPORT_CFG_VRMSK 0x00070000
+#define NPORT_CFG_FBTYP 0x00080000
+
+ npireg_t _unused1;
+ npireg_t stat;
+#define NPORT_STAT_VERS 0x00000007
+#define NPORT_STAT_GBUSY 0x00000008
+#define NPORT_STAT_BBUSY 0x00000010
+#define NPORT_STAT_VRINT 0x00000020
+#define NPORT_STAT_VIDINT 0x00000040
+#define NPORT_STAT_GLMSK 0x00001f80
+#define NPORT_STAT_BLMSK 0x0007e000
+#define NPORT_STAT_BFIRQ 0x00080000
+#define NPORT_STAT_GFIRQ 0x00100000
+
+ npireg_t ustat;
+ npireg_t dreset;
+};
+
+struct newport_regs {
+ struct newport_rexregs set;
+ unsigned long _unused0[0x16e];
+ struct newport_rexregs go;
+ unsigned long _unused1[0x22e];
+ struct newport_cregs cset;
+ unsigned long _unused2[0x1ef];
+ struct newport_cregs cgo;
+};
+extern struct newport_regs *npregs;
+
+/* Reading/writing VC2 registers. */
+#define VC2_REGADDR_INDEX 0x00000000
+#define VC2_REGADDR_IREG 0x00000010
+#define VC2_REGADDR_RAM 0x00000030
+#define VC2_PROTOCOL (NPORT_DMODE_EASACK | 0x00800000 | 0x00040000)
+
+#define VC2_VLINET_ADDR 0x000
+#define VC2_VFRAMET_ADDR 0x400
+#define VC2_CGLYPH_ADDR 0x500
+
+/* Now the Indexed registers of the VC2. */
+#define VC2_IREG_VENTRY 0x00
+#define VC2_IREG_CENTRY 0x01
+#define VC2_IREG_CURSX 0x02
+#define VC2_IREG_CURSY 0x03
+#define VC2_IREG_CCURSX 0x04
+#define VC2_IREG_DENTRY 0x05
+#define VC2_IREG_SLEN 0x06
+#define VC2_IREG_RADDR 0x07
+#define VC2_IREG_VFPTR 0x08
+#define VC2_IREG_VLSPTR 0x09
+#define VC2_IREG_VLIR 0x0a
+#define VC2_IREG_VLCTR 0x0b
+#define VC2_IREG_CTPTR 0x0c
+#define VC2_IREG_WCURSY 0x0d
+#define VC2_IREG_DFPTR 0x0e
+#define VC2_IREG_DLTPTR 0x0f
+#define VC2_IREG_CONTROL 0x10
+#define VC2_IREG_CONFIG 0x20
+
+extern inline void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg,
+ unsigned short val)
+{
+ regs->set.dmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 |
+ NPORT_DMODE_ECINC | VC2_PROTOCOL);
+ regs->set.ddata0.all = (vc2ireg << 24) | (val << 8);
+}
+
+extern inline unsigned short newport_vc2_get(struct newport_regs *regs,
+ unsigned char vc2ireg)
+{
+ regs->set.dmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 |
+ NPORT_DMODE_ECINC | VC2_PROTOCOL);
+ regs->set.ddata0.bytes.b3 = vc2ireg;
+ regs->set.dmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_IREG | NPORT_DMODE_W2 |
+ NPORT_DMODE_ECINC | VC2_PROTOCOL);
+ return regs->set.ddata0.hwords.s1;
+}
+
+/* VC2 Control register bits */
+#define VC2_CTRL_EVIRQ 0x0001
+#define VC2_CTRL_EDISP 0x0002
+#define VC2_CTRL_EVIDEO 0x0004
+#define VC2_CTRL_EDIDS 0x0008
+#define VC2_CTRL_ECURS 0x0010
+#define VC2_CTRL_EGSYNC 0x0020
+#define VC2_CTRL_EILACE 0x0040
+#define VC2_CTRL_ECDISP 0x0080
+#define VC2_CTRL_ECCURS 0x0100
+#define VC2_CTRL_ECG64 0x0200
+#define VC2_CTRL_GLSEL 0x0400
+
+/* Controlling the color map on NEWPORT. */
+#define NCMAP_REGADDR_AREG 0x00000000
+#define NCMAP_REGADDR_ALO 0x00000000
+#define NCMAP_REGADDR_AHI 0x00000010
+#define NCMAP_REGADDR_PBUF 0x00000020
+#define NCMAP_REGADDR_CREG 0x00000030
+#define NCMAP_REGADDR_SREG 0x00000040
+#define NCMAP_REGADDR_RREG 0x00000060
+#define NCMAP_PROTOCOL (0x00008000 | 0x00040000 | 0x00800000)
+
+static inline void newport_cmap_setaddr(struct newport_regs *regs,
+ unsigned short addr)
+{
+ regs->set.dmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
+ NPORT_DMODE_SENDIAN | NPORT_DMODE_ECINC |
+ NCMAP_REGADDR_AREG | NPORT_DMODE_W2);
+ regs->set.ddata0.hwords.s1 = addr;
+ regs->set.dmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
+ NCMAP_REGADDR_PBUF | NPORT_DMODE_W3);
+}
+
+static inline void newport_cmap_setrgb(struct newport_regs *regs,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue)
+{
+ regs->set.ddata0.all =
+ (red << 24) |
+ (green << 16) |
+ (blue << 8);
+}
+
+/* Miscellaneous NEWPORT routines. */
+#define BUSY_TIMEOUT 100000
+static inline int newport_wait(void)
+{
+ int i = 0;
+
+ while(i < BUSY_TIMEOUT)
+ if(!(npregs->cset.stat & NPORT_STAT_GBUSY))
+ break;
+ if(i == BUSY_TIMEOUT)
+ return 1;
+ return 0;
+}
+
+static inline int newport_bfwait(void)
+{
+ int i = 0;
+
+ while(i < BUSY_TIMEOUT)
+ if(!(npregs->cset.stat & NPORT_STAT_BBUSY))
+ break;
+ if(i == BUSY_TIMEOUT)
+ return 1;
+ return 0;
+}
+
+#endif /* !(_SGI_NEWPORT_H) */
diff --git a/drivers/sgi/char/sgicons.c b/drivers/sgi/char/sgicons.c
new file mode 100644
index 000000000..c5051702d
--- /dev/null
+++ b/drivers/sgi/char/sgicons.c
@@ -0,0 +1,28 @@
+/* $Id: sgicons.c,v 1.6 1996/07/29 11:10:22 dm Exp $
+ * sgicons.c: Setting up and registering console I/O on the SGI.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/kernel.h>
+
+extern void newport_init(void);
+extern unsigned long video_mem_base, video_screen_size, video_mem_term;
+
+unsigned long con_type_init(unsigned long start_mem, const char **name)
+{
+ extern int serial_console;
+
+ *name = "NEWPORT";
+
+ if(!serial_console) {
+ printk("Video screen size is %08lx at %08lx\n",
+ video_screen_size, start_mem);
+ video_mem_base = start_mem;
+ start_mem += (video_screen_size * 2);
+ video_mem_term = start_mem;
+
+ newport_init();
+ }
+
+ return start_mem;
+}
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
new file mode 100644
index 000000000..5e346359c
--- /dev/null
+++ b/drivers/sgi/char/sgiserial.c
@@ -0,0 +1,2014 @@
+/* sgiserial.c: Serial port driver for SGI machines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sgialib.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+#include "sgiserial.h"
+
+#define NUM_SERIAL 1 /* One chip on board. */
+#define NUM_CHANNELS (NUM_SERIAL * 2)
+
+struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, };
+struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, };
+struct sgi_zschannel *zs_conschan;
+struct sgi_zschannel *zs_kgdbchan;
+int zs_nodes[NUM_SERIAL] = { 0, };
+
+struct sgi_serial zs_soft[NUM_CHANNELS];
+struct sgi_serial *zs_chain; /* IRQ servicing chain */
+static int zilog_irq = 21;
+
+struct tty_struct zs_ttys[NUM_CHANNELS];
+/** struct tty_struct *zs_constty; **/
+
+/* Console hooks... */
+static int zs_cons_chanout = 0;
+static int zs_cons_chanin = 0;
+struct sgi_serial *zs_consinfo = 0;
+
+static unsigned char kgdb_regs[16] = {
+ 0, 0, 0, /* write 0, 1, 2 */
+ (Rx8 | RxENABLE), /* write 3 */
+ (X16CLK | SB1 | PAR_EVEN), /* write 4 */
+ (Tx8 | TxENAB), /* write 5 */
+ 0, 0, 0, /* write 6, 7, 8 */
+ (NV), /* write 9 */
+ (NRZ), /* write 10 */
+ (TCBR | RCBR), /* write 11 */
+ 0, 0, /* BRG time constant, write 12 + 13 */
+ (BRENABL), /* write 14 */
+ (DCDIE) /* write 15 */
+};
+
+#define ZS_CLOCK 3672000 /* Zilog input clock rate */
+
+DECLARE_TASK_QUEUE(tq_serial);
+
+struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* serial subtype definitions */
+#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/* Debugging... DEBUG_INTR is bad to use when one of the zs
+ * lines is your console ;(
+ */
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+
+#define RS_STROBE_TIME 10
+#define RS_ISR_PASS_LIMIT 256
+
+#define _INLINE_ inline
+
+static void change_speed(struct sgi_serial *info);
+
+static struct tty_struct *serial_table[NUM_CHANNELS];
+static struct termios *serial_termios[NUM_CHANNELS];
+static struct termios *serial_termios_locked[NUM_CHANNELS];
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char tmp_buf[4096]; /* This is cheating */
+static struct semaphore tmp_buf_sem = MUTEX;
+
+static inline int serial_paranoia_check(struct sgi_serial *info,
+ dev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char *badmagic =
+ "Warning: bad magic number for serial struct (%d, %d) in %s\n";
+ static const char *badinfo =
+ "Warning: null sun_serial for (%d, %d) in %s\n";
+
+ if (!info) {
+ printk(badinfo, MAJOR(device), MINOR(device), routine);
+ return 1;
+ }
+ if (info->magic != SERIAL_MAGIC) {
+ printk(badmagic, MAJOR(device), MINOR(device), routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 0 };
+
+/*
+ * Reading and writing Zilog8530 registers. The delays are to make this
+ * driver work on the Sun4 which needs a settling delay after each chip
+ * register access, other machines handle this in hardware via auxiliary
+ * flip-flops which implement the settle time we do in software.
+ */
+static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg)
+{
+ unsigned char retval;
+ volatile unsigned char junk;
+
+ udelay(2);
+ channel->control = reg;
+ junk = ioc_icontrol->istat0;
+ udelay(1);
+ retval = channel->control;
+ return retval;
+}
+
+static inline void write_zsreg(struct sgi_zschannel *channel, unsigned char reg, unsigned char value)
+{
+ volatile unsigned char junk;
+
+ udelay(2);
+ channel->control = reg;
+ junk = ioc_icontrol->istat0;
+ udelay(1);
+ channel->control = value;
+ junk = ioc_icontrol->istat0;
+ return;
+}
+
+static inline void load_zsregs(struct sgi_zschannel *channel, unsigned char *regs)
+{
+ ZS_CLEARERR(channel);
+ ZS_CLEARFIFO(channel);
+ /* Load 'em up */
+ write_zsreg(channel, R4, regs[R4]);
+ write_zsreg(channel, R10, regs[R10]);
+ write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
+ write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+ write_zsreg(channel, R1, regs[R1]);
+ write_zsreg(channel, R9, regs[R9]);
+ write_zsreg(channel, R11, regs[R11]);
+ write_zsreg(channel, R12, regs[R12]);
+ write_zsreg(channel, R13, regs[R13]);
+ write_zsreg(channel, R14, regs[R14]);
+ write_zsreg(channel, R15, regs[R15]);
+ write_zsreg(channel, R3, regs[R3]);
+ write_zsreg(channel, R5, regs[R5]);
+ return;
+}
+
+/* Sets or clears DTR/RTS on the requested line */
+static inline void zs_rtsdtr(struct sgi_serial *ss, int set)
+{
+ if(set) {
+ ss->curregs[5] |= (RTS | DTR);
+ ss->pendregs[5] = ss->curregs[5];
+ write_zsreg(ss->zs_channel, 5, ss->curregs[5]);
+ } else {
+ ss->curregs[5] &= ~(RTS | DTR);
+ ss->pendregs[5] = ss->curregs[5];
+ write_zsreg(ss->zs_channel, 5, ss->curregs[5]);
+ }
+ return;
+}
+
+static inline void kgdb_chaninit(struct sgi_serial *ss, int intson, int bps)
+{
+ int brg;
+
+ if(intson) {
+ kgdb_regs[R1] = INT_ALL_Rx;
+ kgdb_regs[R9] |= MIE;
+ } else {
+ kgdb_regs[R1] = 0;
+ kgdb_regs[R9] &= ~MIE;
+ }
+ brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
+ kgdb_regs[R12] = (brg & 255);
+ kgdb_regs[R13] = ((brg >> 8) & 255);
+ load_zsregs(ss->zs_channel, kgdb_regs);
+}
+
+/* Utility routines for the Zilog */
+static inline int get_zsbaud(struct sgi_serial *ss)
+{
+ struct sgi_zschannel *channel = ss->zs_channel;
+ int brg;
+
+ /* The baud rate is split up between two 8-bit registers in
+ * what is termed 'BRG time constant' format in my docs for
+ * the chip, it is a function of the clk rate the chip is
+ * receiving which happens to be constant.
+ */
+ brg = ((read_zsreg(channel, 13)&0xff) << 8);
+ brg |= (read_zsreg(channel, 12)&0xff);
+ return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor)));
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+ save_flags(flags); cli();
+ if (info->curregs[5] & TxENAB) {
+ info->curregs[5] &= ~TxENAB;
+ info->pendregs[5] &= ~TxENAB;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ }
+ restore_flags(flags);
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_start"))
+ return;
+
+ save_flags(flags); cli();
+ if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) {
+ info->curregs[5] |= TxENAB;
+ info->pendregs[5] = info->curregs[5];
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ }
+ restore_flags(flags);
+}
+
+/* Drop into either the boot monitor or kadb upon receiving a break
+ * from keyboard/console input.
+ */
+static void batten_down_hatches(void)
+{
+ prom_imode();
+#if 0
+ /* If we are doing kadb, we call the debugger
+ * else we just drop into the boot monitor.
+ * Note that we must flush the user windows
+ * first before giving up control.
+ */
+ printk("\n");
+ if((((unsigned long)linux_dbvec)>=DEBUG_FIRSTVADDR) &&
+ (((unsigned long)linux_dbvec)<=DEBUG_LASTVADDR))
+ sp_enter_debugger();
+ else
+ prom_halt();
+
+ /* XXX We want to notify the keyboard driver that all
+ * XXX keys are in the up state or else weird things
+ * XXX happen...
+ */
+#endif
+ return;
+}
+
+/* On receive, this clears errors and the receiver interrupts */
+static inline void rs_recv_clear(struct sgi_zschannel *zsc)
+{
+ volatile unsigned char junk;
+
+ udelay(2);
+ zsc->control = ERR_RES;
+ junk = ioc_icontrol->istat0;
+ udelay(2);
+ zsc->control = RES_H_IUS;
+ junk = ioc_icontrol->istat0;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines. All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt(). They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off. People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible. After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct sgi_serial *info,
+ int event)
+{
+ info->event |= 1 << event;
+ queue_task_irq_off(&info->tqueue, &tq_serial);
+ mark_bh(SERIAL_BH);
+}
+
+extern void breakpoint(void); /* For the KGDB frame character */
+
+static _INLINE_ void receive_chars(struct sgi_serial *info, struct pt_regs *regs)
+{
+ struct tty_struct *tty = info->tty;
+ volatile unsigned char junk;
+ unsigned char ch, stat;
+
+ udelay(2);
+ ch = info->zs_channel->data;
+ junk = ioc_icontrol->istat0;
+ udelay(2);
+ stat = read_zsreg(info->zs_channel, R1);
+
+ /* If this is the console keyboard, we need to handle
+ * L1-A's here.
+ */
+ if(info->is_cons) {
+ if(ch==0) { /* whee, break received */
+ batten_down_hatches();
+ rs_recv_clear(info->zs_channel);
+ return;
+ } else if (ch == 1) {
+ show_state();
+ return;
+ } else if (ch == 2) {
+ show_buffers();
+ return;
+ }
+ /* It is a 'keyboard interrupt' ;-) */
+ wake_up(&keypress_wait);
+ }
+ /* Look for kgdb 'stop' character, consult the gdb documentation
+ * for remote target debugging and arch/sparc/kernel/sparc-stub.c
+ * to see how all this works.
+ */
+ if((info->kgdb_channel) && (ch =='\003')) {
+ /* breakpoint(); */
+ goto clear_and_exit;
+ }
+
+ if(!tty)
+ goto clear_and_exit;
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+ tty->flip.count++;
+ if(stat & PAR_ERR)
+ *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ else if(stat & Rx_OVR)
+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ else if(stat & CRC_ERR)
+ *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ else
+ *tty->flip.flag_buf_ptr++ = 0; /* XXX */
+ *tty->flip.char_buf_ptr++ = ch;
+
+ queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+
+clear_and_exit:
+ rs_recv_clear(info->zs_channel);
+ return;
+}
+
+static _INLINE_ void transmit_chars(struct sgi_serial *info)
+{
+ volatile unsigned char junk;
+
+ /* P3: In theory we have to test readiness here because a
+ * serial console can clog the chip through rs_put_char().
+ * David did not do this. I think he relies on 3-chars FIFO in 8530.
+ * Let's watch for lost _output_ characters. XXX
+ */
+
+ /* SGI ADDENDUM: On most SGI machines, the Zilog does possess
+ * a 16 or 17 byte fifo, so no worries. -dm
+ */
+
+ if (info->x_char) {
+ /* Send next char */
+ udelay(2);
+ info->zs_channel->data = info->x_char;
+ junk = ioc_icontrol->istat0;
+
+ info->x_char = 0;
+ goto clear_and_return;
+ }
+
+ if((info->xmit_cnt <= 0) || info->tty->stopped) {
+ /* That's peculiar... */
+ udelay(2);
+ info->zs_channel->control = RES_Tx_P;
+ junk = ioc_icontrol->istat0;
+ goto clear_and_return;
+ }
+
+ /* Send char */
+ udelay(2);
+ info->zs_channel->data = info->xmit_buf[info->xmit_tail++];
+ junk = ioc_icontrol->istat0;
+
+ info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+
+ if (info->xmit_cnt < WAKEUP_CHARS)
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+ if(info->xmit_cnt <= 0) {
+ udelay(2);
+ info->zs_channel->control = RES_Tx_P;
+ junk = ioc_icontrol->istat0;
+ goto clear_and_return;
+ }
+
+clear_and_return:
+ /* Clear interrupt */
+ udelay(2);
+ info->zs_channel->control = RES_H_IUS;
+ junk = ioc_icontrol->istat0;
+ return;
+}
+
+static _INLINE_ void status_handle(struct sgi_serial *info)
+{
+ volatile unsigned char junk;
+ unsigned char status;
+
+ /* Get status from Read Register 0 */
+ udelay(2);
+ status = info->zs_channel->control;
+ junk = ioc_icontrol->istat0;
+ /* Clear status condition... */
+ udelay(2);
+ info->zs_channel->control = RES_EXT_INT;
+ junk = ioc_icontrol->istat0;
+ /* Clear the interrupt */
+ udelay(2);
+ info->zs_channel->control = RES_H_IUS;
+ junk = ioc_icontrol->istat0;
+
+#if 0
+ if(status & DCD) {
+ if((info->tty->termios->c_cflag & CRTSCTS) &&
+ ((info->curregs[3] & AUTO_ENAB)==0)) {
+ info->curregs[3] |= AUTO_ENAB;
+ info->pendregs[3] |= AUTO_ENAB;
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ }
+ } else {
+ if((info->curregs[3] & AUTO_ENAB)) {
+ info->curregs[3] &= ~AUTO_ENAB;
+ info->pendregs[3] &= ~AUTO_ENAB;
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ }
+ }
+#endif
+ /* Whee, if this is console input and this is a
+ * 'break asserted' status change interrupt, call
+ * the boot prom.
+ */
+ if((status & BRK_ABRT) && info->break_abort)
+ batten_down_hatches();
+
+ /* XXX Whee, put in a buffer somewhere, the status information
+ * XXX whee whee whee... Where does the information go...
+ */
+ return;
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct sgi_serial * info = (struct sgi_serial *) dev_id;
+ unsigned char zs_intreg;
+
+ zs_intreg = read_zsreg(info->zs_channel, 3);
+
+ /* NOTE: The read register 3, which holds the irq status,
+ * does so for both channels on each chip. Although
+ * the status value itself must be read from the A
+ * channel and is only valid when read from channel A.
+ * Yes... broken hardware...
+ */
+#define CHAN_A_IRQMASK (CHARxIP | CHATxIP | CHAEXT)
+#define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
+
+ /* *** Chip 1 *** */
+ /* Channel A -- /dev/ttya, could be the console */
+ if(zs_intreg & CHAN_A_IRQMASK) {
+ if (zs_intreg & CHARxIP)
+ receive_chars(info, regs);
+ if (zs_intreg & CHATxIP)
+ transmit_chars(info);
+ if (zs_intreg & CHAEXT)
+ status_handle(info);
+ }
+
+ info=info->zs_next;
+
+ /* Channel B -- /dev/ttyb, could be the console */
+ if(zs_intreg & CHAN_B_IRQMASK) {
+ if (zs_intreg & CHBRxIP)
+ receive_chars(info, regs);
+ if (zs_intreg & CHBTxIP)
+ transmit_chars(info);
+ if (zs_intreg & CHBEXT)
+ status_handle(info);
+ }
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+ run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+ struct sgi_serial *info = (struct sgi_serial *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred. The path of
+ * hangup processing is:
+ *
+ * serial interrupt routine -> (scheduler tqueue) ->
+ * do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ *
+ */
+static void do_serial_hangup(void *private_)
+{
+ struct sgi_serial *info = (struct sgi_serial *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ tty_hangup(tty);
+}
+
+
+/*
+ * This subroutine is called when the RS_TIMER goes off. It is used
+ * by the serial driver to handle ports that do not have an interrupt
+ * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530.
+ */
+
+static void rs_timer(void)
+{
+ printk("rs_timer called\n");
+ prom_halt();
+ return;
+}
+
+static int startup(struct sgi_serial * info)
+{
+ volatile unsigned char junk;
+ unsigned long flags;
+
+ if (info->flags & ZILOG_INITIALIZED)
+ return 0;
+
+ if (!info->xmit_buf) {
+ info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
+ if (!info->xmit_buf)
+ return -ENOMEM;
+ }
+
+ save_flags(flags); cli();
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up ttys%d (irq %d)...", info->line, info->irq);
+#endif
+
+ /*
+ * Clear the FIFO buffers and disable them
+ * (they will be reenabled in change_speed())
+ */
+ ZS_CLEARFIFO(info->zs_channel);
+ info->xmit_fifo_size = 1;
+
+ /*
+ * Clear the interrupt registers.
+ */
+ udelay(2);
+ info->zs_channel->control = ERR_RES;
+ junk = ioc_icontrol->istat0;
+ udelay(2);
+ info->zs_channel->control = RES_H_IUS;
+ junk = ioc_icontrol->istat0;
+
+ /*
+ * Now, initialize the Zilog
+ */
+ zs_rtsdtr(info, 1);
+
+ /*
+ * Finally, enable sequencing and interrupts
+ */
+ info->curregs[1] |= (info->curregs[1] & ~0x18) | (EXT_INT_ENAB|INT_ALL_Rx);
+ info->pendregs[1] = info->curregs[1];
+ info->curregs[3] |= (RxENABLE | Rx8);
+ info->pendregs[3] = info->curregs[3];
+ /* We enable Tx interrupts as needed. */
+ info->curregs[5] |= (TxENAB | Tx8);
+ info->pendregs[5] = info->curregs[5];
+ info->curregs[9] |= (NV | MIE);
+ info->pendregs[9] = info->curregs[9];
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ write_zsreg(info->zs_channel, 9, info->curregs[9]);
+
+ /*
+ * And clear the interrupt registers again for luck.
+ */
+ udelay(2);
+ info->zs_channel->control = ERR_RES;
+ junk = ioc_icontrol->istat0;
+ udelay(2);
+ info->zs_channel->control = RES_H_IUS;
+ junk = ioc_icontrol->istat0;
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ /*
+ * Set up serial timers...
+ */
+#if 0 /* Works well and stops the machine. */
+ timer_table[RS_TIMER].expires = jiffies + 2;
+ timer_active |= 1 << RS_TIMER;
+#endif
+
+ /*
+ * and set the speed of the serial port
+ */
+ change_speed(info);
+
+ info->flags |= ZILOG_INITIALIZED;
+ restore_flags(flags);
+ return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct sgi_serial * info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ZILOG_INITIALIZED))
+ return;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("Shutting down serial port %d (irq %d)....", info->line,
+ info->irq);
+#endif
+
+ save_flags(flags); cli(); /* Disable interrupts */
+
+ if (info->xmit_buf) {
+ free_page((unsigned long) info->xmit_buf);
+ info->xmit_buf = 0;
+ }
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ZILOG_INITIALIZED;
+ restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct sgi_serial *info)
+{
+ unsigned short port;
+ unsigned cflag;
+ int i;
+ int brg;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ cflag = info->tty->termios->c_cflag;
+ if (!(port = info->port))
+ return;
+ i = cflag & CBAUD;
+ if (i & CBAUDEX) {
+ /* XXX CBAUDEX is not obeyed.
+ * It is impossible at a 32bits SPARC.
+ * But we have to report this to user ... someday.
+ */
+ i = B9600;
+ }
+ if (i == 0) {
+ /* XXX B0, hangup the line. */
+ do_serial_hangup(info);
+ } else if (baud_table[i]) {
+ info->zs_baud = baud_table[i];
+ info->clk_divisor = 16;
+
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = TCBR | RCBR;
+ brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+ info->curregs[12] = (brg & 255);
+ info->curregs[13] = ((brg >> 8) & 255);
+ info->curregs[14] = BRENABL;
+ }
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->curregs[3] &= ~(0xc0);
+ info->curregs[3] |= Rx5;
+ info->pendregs[3] = info->curregs[3];
+ info->curregs[5] &= ~(0xe0);
+ info->curregs[5] |= Tx5;
+ info->pendregs[5] = info->curregs[5];
+ break;
+ case CS6:
+ info->curregs[3] &= ~(0xc0);
+ info->curregs[3] |= Rx6;
+ info->pendregs[3] = info->curregs[3];
+ info->curregs[5] &= ~(0xe0);
+ info->curregs[5] |= Tx6;
+ info->pendregs[5] = info->curregs[5];
+ break;
+ case CS7:
+ info->curregs[3] &= ~(0xc0);
+ info->curregs[3] |= Rx7;
+ info->pendregs[3] = info->curregs[3];
+ info->curregs[5] &= ~(0xe0);
+ info->curregs[5] |= Tx7;
+ info->pendregs[5] = info->curregs[5];
+ break;
+ case CS8:
+ default: /* defaults to 8 bits */
+ info->curregs[3] &= ~(0xc0);
+ info->curregs[3] |= Rx8;
+ info->pendregs[3] = info->curregs[3];
+ info->curregs[5] &= ~(0xe0);
+ info->curregs[5] |= Tx8;
+ info->pendregs[5] = info->curregs[5];
+ break;
+ }
+ info->curregs[4] &= ~(0x0c);
+ if (cflag & CSTOPB) {
+ info->curregs[4] |= SB2;
+ } else {
+ info->curregs[4] |= SB1;
+ }
+ info->pendregs[4] = info->curregs[4];
+ if (cflag & PARENB) {
+ info->curregs[4] |= PAR_ENA;
+ info->pendregs[4] |= PAR_ENA;
+ } else {
+ info->curregs[4] &= ~PAR_ENA;
+ info->pendregs[4] &= ~PAR_ENA;
+ }
+ if (!(cflag & PARODD)) {
+ info->curregs[4] |= PAR_EVEN;
+ info->pendregs[4] |= PAR_EVEN;
+ } else {
+ info->curregs[4] &= ~PAR_EVEN;
+ info->pendregs[4] &= ~PAR_EVEN;
+ }
+
+ /* Load up the new values */
+ load_zsregs(info->zs_channel, info->curregs);
+
+ return;
+}
+
+/* This is for console output over ttya/ttyb */
+static void rs_put_char(char ch)
+{
+ struct sgi_zschannel *chan = zs_conschan;
+ volatile unsigned char junk;
+ int flags, loops = 0;
+
+ save_flags(flags); cli();
+ while(((junk = chan->control) & Tx_BUF_EMP)==0 && loops < 10000) {
+ loops++;
+ udelay(2);
+ }
+
+ udelay(2);
+ chan->data = ch;
+ junk = ioc_icontrol->istat0;
+ restore_flags(flags);
+}
+
+/* These are for receiving and sending characters under the kgdb
+ * source level kernel debugger.
+ */
+void putDebugChar(char kgdb_char)
+{
+ struct sgi_zschannel *chan = zs_kgdbchan;
+ volatile unsigned char junk;
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ udelay(2);
+ while((chan->control & Tx_BUF_EMP)==0)
+ udelay(2);
+
+ udelay(2);
+ chan->data = kgdb_char;
+ junk = ioc_icontrol->istat0;
+ restore_flags(flags);
+}
+
+char getDebugChar(void)
+{
+ struct sgi_zschannel *chan = zs_kgdbchan;
+ unsigned char junk;
+
+ while((chan->control & Rx_CH_AV)==0)
+ udelay(2);
+
+ junk = ioc_icontrol->istat0;
+ udelay(2);
+ return chan->data;
+}
+
+/*
+ * Fair output driver allows a process to speak.
+ */
+static void rs_fair_output(void)
+{
+ int left; /* Output no more than that */
+ unsigned long flags;
+ struct sgi_serial *info = zs_consinfo;
+ volatile unsigned char junk;
+ char c;
+
+ if (info == 0) return;
+ if (info->xmit_buf == 0) return;
+
+ save_flags(flags); cli();
+ left = info->xmit_cnt;
+ while (left != 0) {
+ c = info->xmit_buf[info->xmit_tail];
+ info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+ restore_flags(flags);
+
+ rs_put_char(c);
+
+ save_flags(flags); cli();
+ left = MIN(info->xmit_cnt, left-1);
+ }
+
+ /* Last character is being transmitted now (hopefully). */
+ udelay(2);
+ zs_conschan->control = RES_Tx_P;
+ junk = ioc_icontrol->istat0;
+
+ restore_flags(flags);
+ return;
+}
+
+/*
+ * zs_console_print is registered for printk.
+ */
+static void zs_console_print(const char *p)
+{
+ char c;
+
+ while((c=*(p++)) != 0) {
+ if(c == '\n')
+ rs_put_char('\r');
+ rs_put_char(c);
+ }
+
+ /* Comment this if you want to have a strict interrupt-driven output */
+ rs_fair_output();
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+ return;
+
+ if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !info->xmit_buf)
+ return;
+
+ /* Enable transmitter */
+ save_flags(flags); cli();
+ info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+ info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ info->curregs[5] |= TxENAB;
+ info->pendregs[5] |= TxENAB;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+
+ /*
+ * Send a first (bootstrapping) character. A best solution is
+ * to call transmit_chars() here which handles output in a
+ * generic way. Current transmit_chars() not only transmits,
+ * but resets interrupts also what we do not desire here.
+ * XXX Discuss with David.
+ */
+ if (info->zs_channel->control & Tx_BUF_EMP) {
+ volatile unsigned char junk;
+
+ /* Send char */
+ udelay(2);
+ info->zs_channel->data = info->xmit_buf[info->xmit_tail++];
+ junk = ioc_icontrol->istat0;
+ info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+ }
+ restore_flags(flags);
+}
+
+static int rs_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
+{
+ int c, total = 0;
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write"))
+ return 0;
+
+ if (!tty || !info->xmit_buf)
+ return 0;
+
+ save_flags(flags);
+ while (1) {
+ cli();
+ c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+
+ if (from_user) {
+ down(&tmp_buf_sem);
+ memcpy_fromfs(tmp_buf, buf, c);
+ c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ up(&tmp_buf_sem);
+ } else
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ total += c;
+ }
+ if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+ !(info->curregs[5] & TxENAB)) {
+ /* Enable transmitter */
+ info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+ info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ info->curregs[5] |= TxENAB;
+ info->pendregs[5] |= TxENAB;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ }
+ restore_flags(flags);
+ return total;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+ int ret;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+ return 0;
+ ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+ return 0;
+ return info->xmit_cnt;
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+ return;
+ cli();
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ sti();
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("throttle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+ return;
+
+ if (I_IXOFF(tty))
+ info->x_char = STOP_CHAR(tty);
+
+ /* Turn off RTS line */
+ cli();
+ info->curregs[5] &= ~RTS;
+ info->pendregs[5] &= ~RTS;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ sti();
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ info->x_char = START_CHAR(tty);
+ }
+
+ /* Assert RTS line */
+ cli();
+ info->curregs[5] |= RTS;
+ info->pendregs[5] |= RTS;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ sti();
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct sgi_serial * info,
+ struct serial_struct * retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = info->type;
+ tmp.line = info->line;
+ tmp.port = info->port;
+ tmp.irq = info->irq;
+ tmp.flags = info->flags;
+ tmp.baud_base = info->baud_base;
+ tmp.close_delay = info->close_delay;
+ tmp.closing_wait = info->closing_wait;
+ tmp.custom_divisor = info->custom_divisor;
+ memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
+ return 0;
+}
+
+static int set_serial_info(struct sgi_serial * info,
+ struct serial_struct * new_info)
+{
+ struct serial_struct new_serial;
+ struct sgi_serial old_info;
+ int retval = 0;
+
+ if (!new_info)
+ return -EFAULT;
+ memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
+ old_info = *info;
+
+ if (!suser()) {
+ if ((new_serial.baud_base != info->baud_base) ||
+ (new_serial.type != info->type) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ZILOG_USR_MASK) !=
+ (info->flags & ~ZILOG_USR_MASK)))
+ return -EPERM;
+ info->flags = ((info->flags & ~ZILOG_USR_MASK) |
+ (new_serial.flags & ZILOG_USR_MASK));
+ info->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ if (info->count > 1)
+ return -EBUSY;
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+
+ info->baud_base = new_serial.baud_base;
+ info->flags = ((info->flags & ~ZILOG_FLAGS) |
+ (new_serial.flags & ZILOG_FLAGS));
+ info->type = new_serial.type;
+ info->close_delay = new_serial.close_delay;
+ info->closing_wait = new_serial.closing_wait;
+
+check_and_exit:
+ retval = startup(info);
+ return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct sgi_serial * info, unsigned int *value)
+{
+ volatile unsigned char junk;
+ unsigned char status;
+
+ cli();
+ udelay(2);
+ status = info->zs_channel->control;
+ junk = ioc_icontrol->istat0;
+ sti();
+ put_user(status,value);
+ return 0;
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break( struct sgi_serial * info, int duration)
+{
+ if (!info->port)
+ return;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + duration;
+ cli();
+ write_zsreg(info->zs_channel, 5, (info->curregs[5] | SND_BRK));
+ schedule();
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ sti();
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ int error;
+ struct sgi_serial * info = (struct sgi_serial *)tty->driver_data;
+ int retval;
+
+ if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+ return -ENODEV;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
+ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ send_break(info, HZ/4); /* 1/4 second */
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ return 0;
+ case TIOCGSOFTCAR:
+ error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
+ if (error)
+ return error;
+ put_fs_long(C_CLOCAL(tty) ? 1 : 0,
+ (unsigned long *) arg);
+ return 0;
+ case TIOCSSOFTCAR:
+ arg = get_fs_long((unsigned long *) arg);
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+ case TIOCGSERIAL:
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct));
+ if (error)
+ return error;
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int));
+ if (error)
+ return error;
+ else
+ return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct sgi_serial));
+ if (error)
+ return error;
+ memcpy_tofs((struct sun_serial *) arg,
+ info, sizeof(struct sgi_serial));
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+
+ if (tty->termios->c_cflag == old_termios->c_cflag)
+ return;
+
+ change_speed(info);
+
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ rs_start(tty);
+ }
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * ZILOG structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ struct sgi_serial * info = (struct sgi_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+ return;
+
+ save_flags(flags); cli();
+
+ if (tty_hung_up_p(filp)) {
+ restore_flags(flags);
+ return;
+ }
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_close ttys%d, count = %d\n", info->line, info->count);
+#endif
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("rs_close: bad serial port count; tty->count is 1, "
+ "info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+ printk("rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, info->count);
+ info->count = 0;
+ }
+ if (info->count) {
+ restore_flags(flags);
+ return;
+ }
+ info->flags |= ZILOG_CLOSING;
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ZILOG_NORMAL_ACTIVE)
+ info->normal_termios = *tty->termios;
+ if (info->flags & ZILOG_CALLOUT_ACTIVE)
+ info->callout_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receive line status interrupts, and tell the
+ * interrupt driver to stop checking the data ready bit in the
+ * line status register.
+ */
+ /** if (!info->iscons) ... **/
+ info->curregs[3] &= ~RxENABLE;
+ info->pendregs[3] = info->curregs[3];
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ info->curregs[1] &= ~(0x18);
+ info->pendregs[1] = info->curregs[1];
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ ZS_CLEARFIFO(info->zs_channel);
+
+ shutdown(info);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+ if (tty->ldisc.num != ldiscs[N_TTY].num) {
+ if (tty->ldisc.close)
+ (tty->ldisc.close)(tty);
+ tty->ldisc = ldiscs[N_TTY];
+ tty->termios->c_line = N_TTY;
+ if (tty->ldisc.open)
+ (tty->ldisc.open)(tty);
+ }
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + info->close_delay;
+ schedule();
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
+ ZILOG_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+ restore_flags(flags);
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+void rs_hangup(struct tty_struct *tty)
+{
+ struct sgi_serial * info = (struct sgi_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+ return;
+
+ rs_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ info->count = 0;
+ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE);
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ struct sgi_serial *info)
+{
+ struct wait_queue wait = { current, NULL };
+ int retval;
+ int do_clocal = 0;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (info->flags & ZILOG_CLOSING) {
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ZILOG_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+#else
+ return -EAGAIN;
+#endif
+ }
+
+ /*
+ * If this is a callout device, then just make sure the normal
+ * device isn't being used.
+ */
+ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+ if (info->flags & ZILOG_NORMAL_ACTIVE)
+ return -EBUSY;
+ if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ (info->flags & ZILOG_SESSION_LOCKOUT) &&
+ (info->session != current->session))
+ return -EBUSY;
+ if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ (info->flags & ZILOG_PGRP_LOCKOUT) &&
+ (info->pgrp != current->pgrp))
+ return -EBUSY;
+ info->flags |= ZILOG_CALLOUT_ACTIVE;
+ return 0;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ if (info->flags & ZILOG_CALLOUT_ACTIVE)
+ return -EBUSY;
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (info->flags & ZILOG_CALLOUT_ACTIVE) {
+ if (info->normal_termios.c_cflag & CLOCAL)
+ do_clocal = 1;
+ } else {
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+ }
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready before block: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ info->count--;
+ info->blocked_open++;
+ while (1) {
+ cli();
+ if (!(info->flags & ZILOG_CALLOUT_ACTIVE))
+ zs_rtsdtr(info, 1);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ZILOG_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ZILOG_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#else
+ retval = -EAGAIN;
+#endif
+ break;
+ }
+ if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ !(info->flags & ZILOG_CLOSING) && do_clocal)
+ break;
+ if (current->signal & ~current->blocked) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ info->count++;
+ info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready after blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ if (retval)
+ return retval;
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its ZILOG structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ struct sgi_serial *info;
+ int retval, line;
+
+ line = MINOR(tty->device) - tty->driver.minor_start;
+ /* The zilog lines for the mouse/keyboard must be
+ * opened using their respective drivers.
+ */
+ if ((line < 0) || (line >= NUM_CHANNELS))
+ return -ENODEV;
+ info = zs_soft + line;
+ /* Is the kgdb running over this line? */
+ if (info->kgdb_channel)
+ return -ENODEV;
+ if (serial_paranoia_check(info, tty->device, "rs_open"))
+ return -ENODEV;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+ info->count);
+#endif
+ info->count++;
+ tty->driver_data = info;
+ info->tty = tty;
+
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval)
+ return retval;
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open returning after block_til_ready with %d\n",
+ retval);
+#endif
+ return retval;
+ }
+
+ if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->normal_termios;
+ else
+ *tty->termios = info->callout_termios;
+ change_speed(info);
+ }
+
+ info->session = current->session;
+ info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open ttys%d successful...", info->line);
+#endif
+ return 0;
+}
+
+/* Finally, routines used to initialize the serial driver. */
+
+static void show_serial_version(void)
+{
+ printk("SGI Zilog8530 serial driver version 1.00\n");
+}
+
+/* Return layout for the requested zs chip number. */
+static inline struct sgi_zslayout *get_zs(int chip)
+{
+ extern struct hpc3_miscregs *hpc3mregs;
+
+ if(chip > 0) {
+ prom_printf("Wheee, bogus zs chip number requested.\n");
+ prom_getchar();
+ romvec->imode();
+ }
+ return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd);
+
+}
+
+extern void register_console(void (*proc)(const char *));
+
+static inline void
+rs_cons_check(struct sgi_serial *ss, int channel)
+{
+ int i, o, io;
+ static consout_registered = 0;
+ static msg_printed = 0;
+
+ i = o = io = 0;
+
+ /* Is this one of the serial console lines? */
+ if((zs_cons_chanout != channel) &&
+ (zs_cons_chanin != channel))
+ return;
+ zs_conschan = ss->zs_channel;
+ zs_consinfo = ss;
+
+ /* Register the console output putchar, if necessary */
+ if((zs_cons_chanout == channel)) {
+ o = 1;
+ /* double whee.. */
+ if(!consout_registered) {
+ register_console(zs_console_print);
+ consout_registered = 1;
+ }
+ }
+
+ /* If this is console input, we handle the break received
+ * status interrupt on this line to mean prom_halt().
+ */
+ if(zs_cons_chanin == channel) {
+ ss->break_abort = 1;
+ i = 1;
+ }
+ if(o && i)
+ io = 1;
+ if(ss->zs_baud != 9562) { /* Don't ask... */
+ prom_printf("BAD console baud rate %d\n", ss->zs_baud);
+ prom_getchar();
+ prom_imode();
+ panic("Console baud rate weirdness");
+ }
+
+ /* Set flag variable for this port so that it cannot be
+ * opened for other uses by accident.
+ */
+ ss->is_cons = 1;
+
+ if(io) {
+ if(!msg_printed) {
+ printk("zs%d: console I/O\n", ((channel>>1)&1));
+ msg_printed = 1;
+ }
+ } else {
+ printk("zs%d: console %s\n", ((channel>>1)&1),
+ (i==1 ? "input" : (o==1 ? "output" : "WEIRD")));
+ }
+}
+
+volatile int test_done;
+
+/* rs_init inits the driver */
+int rs_init(void)
+{
+ int chip, channel, i, flags;
+ struct sgi_serial *info;
+
+ /* Setup base handler, and timer table. */
+ init_bh(SERIAL_BH, do_serial_bh);
+ timer_table[RS_TIMER].fn = rs_timer;
+ timer_table[RS_TIMER].expires = 0;
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+ /* SGI: Not all of this is exactly right for us. */
+
+ memset(&serial_driver, 0, sizeof(struct tty_driver));
+ serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.name = "ttyS";
+ serial_driver.major = TTY_MAJOR;
+ serial_driver.minor_start = 64;
+ serial_driver.num = NUM_CHANNELS;
+ serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver.subtype = SERIAL_TYPE_NORMAL;
+ serial_driver.init_termios = tty_std_termios;
+
+ serial_driver.init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver.flags = TTY_DRIVER_REAL_RAW;
+ serial_driver.refcount = &serial_refcount;
+ serial_driver.table = serial_table;
+ serial_driver.termios = serial_termios;
+ serial_driver.termios_locked = serial_termios_locked;
+
+ serial_driver.open = rs_open;
+ serial_driver.close = rs_close;
+ serial_driver.write = rs_write;
+ serial_driver.flush_chars = rs_flush_chars;
+ serial_driver.write_room = rs_write_room;
+ serial_driver.chars_in_buffer = rs_chars_in_buffer;
+ serial_driver.flush_buffer = rs_flush_buffer;
+ serial_driver.ioctl = rs_ioctl;
+ serial_driver.throttle = rs_throttle;
+ serial_driver.unthrottle = rs_unthrottle;
+ serial_driver.set_termios = rs_set_termios;
+ serial_driver.stop = rs_stop;
+ serial_driver.start = rs_start;
+ serial_driver.hangup = rs_hangup;
+
+ /*
+ * The callout device is just like normal device except for
+ * major number and the subtype code.
+ */
+ callout_driver = serial_driver;
+ callout_driver.name = "cua";
+ callout_driver.major = TTYAUX_MAJOR;
+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+ if (tty_register_driver(&serial_driver))
+ panic("Couldn't register serial driver\n");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver\n");
+
+ save_flags(flags); cli();
+
+ /* Set up our interrupt linked list */
+ zs_chain = &zs_soft[0];
+ zs_soft[0].zs_next = &zs_soft[1];
+ zs_soft[1].zs_next = 0;
+
+ for(chip = 0; chip < NUM_SERIAL; chip++) {
+ /* If we are doing kgdb over one of the channels on
+ * chip zero, kgdb_channel will be set to 1 by the
+ * rs_kgdb_hook() routine below.
+ */
+ if(!zs_chips[chip]) {
+ zs_chips[chip] = get_zs(chip);
+ /* Two channels per chip */
+ zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
+ zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+ zs_soft[(chip*2)].kgdb_channel = 0;
+ zs_soft[(chip*2)+1].kgdb_channel = 0;
+ }
+ /* First, set up channel A on this chip. */
+ channel = chip * 2;
+ zs_soft[channel].zs_channel = zs_channels[channel];
+ zs_soft[channel].change_needed = 0;
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+ zs_soft[channel].cons_mouse = 0;
+ /* If not keyboard/mouse and is console serial
+ * line, then enable receiver interrupts.
+ */
+ if(zs_soft[channel].is_cons) {
+ write_zsreg(zs_soft[channel].zs_channel, R1,
+ (EXT_INT_ENAB | INT_ALL_Rx));
+ write_zsreg(zs_soft[channel].zs_channel, R9, (NV | MIE));
+ write_zsreg(zs_soft[channel].zs_channel, R10, (NRZ));
+ write_zsreg(zs_soft[channel].zs_channel, R3, (Rx8|RxENABLE));
+ write_zsreg(zs_soft[channel].zs_channel, R5, (Tx8 | TxENAB));
+ }
+ /* If this is the kgdb line, enable interrupts because we
+ * now want to receive the 'control-c' character from the
+ * client attached to us asynchronously.
+ */
+ if(zs_soft[channel].kgdb_channel)
+ kgdb_chaninit(&zs_soft[channel], 1,
+ zs_soft[channel].zs_baud);
+
+ /* Now, channel B */
+ channel++;
+ zs_soft[channel].zs_channel = zs_channels[channel];
+ zs_soft[channel].change_needed = 0;
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+ zs_soft[channel].cons_keyb = 0;
+ /* If console serial line, then enable receiver interrupts. */
+ if(zs_soft[channel].is_cons) {
+ write_zsreg(zs_soft[channel].zs_channel, R1,
+ (EXT_INT_ENAB | INT_ALL_Rx));
+ write_zsreg(zs_soft[channel].zs_channel, R9,
+ (NV | MIE));
+ write_zsreg(zs_soft[channel].zs_channel, R10,
+ (NRZ));
+ write_zsreg(zs_soft[channel].zs_channel, R3,
+ (Rx8|RxENABLE));
+ write_zsreg(zs_soft[channel].zs_channel, R5,
+ (Tx8 | TxENAB | RTS | DTR));
+ }
+ }
+
+ for(info=zs_chain, i=0; info; info = info->zs_next, i++)
+ {
+ info->magic = SERIAL_MAGIC;
+ info->port = (int) info->zs_channel;
+ info->line = i;
+ info->tty = 0;
+ info->irq = zilog_irq;
+ info->custom_divisor = 16;
+ info->close_delay = 50;
+ info->closing_wait = 3000;
+ info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+ info->tqueue.routine = do_softint;
+ info->tqueue.data = info;
+ info->tqueue_hangup.routine = do_serial_hangup;
+ info->tqueue_hangup.data = info;
+ info->callout_termios =callout_driver.init_termios;
+ info->normal_termios = serial_driver.init_termios;
+ info->open_wait = 0;
+ info->close_wait = 0;
+ printk("tty%02d at 0x%04x (irq = %d)", info->line,
+ info->port, info->irq);
+ printk(" is a Zilog8530\n");
+ }
+
+ if (request_irq(zilog_irq, rs_interrupt, (SA_INTERRUPT),
+ "Zilog8530", zs_chain))
+ panic("Unable to attach zs intr\n");
+ restore_flags(flags);
+
+ return 0;
+}
+
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+/* SGI: Unused at this time, just here to make things link. */
+int register_serial(struct serial_struct *req)
+{
+ return -1;
+}
+
+void unregister_serial(int line)
+{
+ return;
+}
+
+/* Hooks for running a serial console. con_init() calls this if the
+ * console is being run over one of the ttya/ttyb serial ports.
+ * 'chip' should be zero, as chip 1 drives the mouse/keyboard.
+ * 'channel' is decoded as 0=TTYA 1=TTYB, note that the channels
+ * are addressed backwards, channel B is first, then channel A.
+ */
+void
+rs_cons_hook(int chip, int out, int line)
+{
+ int channel;
+
+ if(chip)
+ panic("rs_cons_hook called with chip not zero");
+ if(line != 1 && line != 2)
+ panic("rs_cons_hook called with line not ttya or ttyb");
+ channel = line - 1;
+ if(!zs_chips[chip]) {
+ zs_chips[chip] = get_zs(chip);
+ /* Two channels per chip */
+ zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
+ zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+ }
+ zs_soft[channel].zs_channel = zs_channels[channel];
+ zs_soft[channel].change_needed = 0;
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+ if(out)
+ zs_cons_chanout = ((chip * 2) + channel);
+ else
+ zs_cons_chanin = ((chip * 2) + channel);
+ rs_cons_check(&zs_soft[channel], channel);
+}
+
+/* This is called at boot time to prime the kgdb serial debugging
+ * serial line. The 'tty_num' argument is 0 for /dev/ttyd2 and 1 for
+ * /dev/ttyd1 (yes they are backwards on purpose) which is determined
+ * in setup_arch() from the boot command line flags.
+ */
+void
+rs_kgdb_hook(int tty_num)
+{
+ int chip = 0;
+
+ if(!zs_chips[chip]) {
+ zs_chips[chip] = get_zs(chip);
+ /* Two channels per chip */
+ zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
+ zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+ }
+ zs_soft[tty_num].zs_channel = zs_channels[tty_num];
+ zs_kgdbchan = zs_soft[tty_num].zs_channel;
+ zs_soft[tty_num].change_needed = 0;
+ zs_soft[tty_num].clk_divisor = 16;
+ zs_soft[tty_num].zs_baud = get_zsbaud(&zs_soft[tty_num]);
+ zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */
+ zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */
+
+ /* Turn on transmitter/receiver at 8-bits/char */
+ kgdb_chaninit(&zs_soft[tty_num], 0, 9600);
+ ZS_CLEARERR(zs_kgdbchan);
+ udelay(5);
+ ZS_CLEARFIFO(zs_kgdbchan);
+}
diff --git a/drivers/sgi/char/sgiserial.h b/drivers/sgi/char/sgiserial.h
new file mode 100644
index 000000000..35f18cab7
--- /dev/null
+++ b/drivers/sgi/char/sgiserial.h
@@ -0,0 +1,444 @@
+/* sgiserial.h: Definitions for the SGI Zilog85C30 serial driver.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _SGI_SERIAL_H
+#define _SGI_SERIAL_H
+
+/* Just one channel */
+struct sgi_zschannel {
+#ifdef __MIPSEB__
+ volatile unsigned char unused0[3];
+ volatile unsigned char control;
+ volatile unsigned char unused1[3];
+ volatile unsigned char data;
+#else /* __MIPSEL__ */
+ volatile unsigned char control;
+ volatile unsigned char unused0[3];
+ volatile unsigned char data;
+ volatile unsigned char unused1[3];
+#endif
+};
+
+/* The address space layout for each zs chip. Yes they are
+ * backwards.
+ */
+struct sgi_zslayout {
+ struct sgi_zschannel channelB;
+ struct sgi_zschannel channelA;
+};
+
+#define NUM_ZSREGS 16
+
+struct serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait; /* time to wait before closing */
+ unsigned short closing_wait2; /* no longer used... */
+ int reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output. 65535 means don't wait at all.
+ */
+#define ZILOG_CLOSING_WAIT_INF 0
+#define ZILOG_CLOSING_WAIT_NONE 65535
+
+/*
+ * Definitions for ZILOG_struct (and serial_struct) flags field
+ */
+#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+ on the callout port */
+#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
+#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */
+#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ZILOG_SPD_MASK 0x0030
+#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
+
+#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
+#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */
+
+#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
+#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
+#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
+
+#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */
+#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */
+#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
+#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
+#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
+#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */
+#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */
+#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct sgi_serial {
+ struct sgi_serial *zs_next; /* For IRQ servicing chain */
+ struct sgi_zschannel *zs_channel; /* Channel registers */
+ unsigned char read_reg_zero;
+
+ char soft_carrier; /* Use soft carrier on this channel */
+ char cons_keyb; /* Channel runs the keyboard */
+ char cons_mouse; /* Channel runs the mouse */
+ char break_abort; /* Is serial console in, so process brk/abrt */
+ char kgdb_channel; /* Kgdb is running on this channel */
+ char is_cons; /* Is this our console. */
+
+ /* We need to know the current clock divisor
+ * to read the bps rate the chip has currently
+ * loaded.
+ */
+ unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
+ int zs_baud;
+
+ /* Current write register values */
+ unsigned char curregs[NUM_ZSREGS];
+
+ /* Values we need to set next opportunity */
+ unsigned char pendregs[NUM_ZSREGS];
+
+ char change_needed;
+
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+ int flags; /* defined in tty.h */
+ int type; /* UART type */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct tq_struct tqueue;
+ struct tq_struct tqueue_hangup;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+};
+
+
+#define SERIAL_MAGIC 0x5301
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+/* The Zilog register set */
+
+#define FLAG 0x7e
+
+/* Write Register 0 */
+#define R0 0 /* Register selects */
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define R5 5
+#define R6 6
+#define R7 7
+#define R8 8
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+
+#define NULLCODE 0 /* Null Code */
+#define POINT_HIGH 0x8 /* Select upper half of registers */
+#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
+#define SEND_ABORT 0x18 /* HDLC Abort */
+#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
+#define RES_Tx_P 0x28 /* Reset TxINT Pending */
+#define ERR_RES 0x30 /* Error Reset */
+#define RES_H_IUS 0x38 /* Reset highest IUS */
+
+#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
+#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
+#define RES_EOM_L 0xC0 /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
+#define TxINT_ENAB 0x2 /* Tx Int Enable */
+#define PAR_SPEC 0x4 /* Parity is special condition */
+
+#define RxINT_DISAB 0 /* Rx Int Disable */
+#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
+#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
+#define INT_ERR_Rx 0x18 /* Int on error only */
+
+#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
+#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
+#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define RxENABLE 0x1 /* Rx Enable */
+#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
+#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
+#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
+#define ENT_HM 0x10 /* Enter Hunt Mode */
+#define AUTO_ENAB 0x20 /* Auto Enables */
+#define Rx5 0x0 /* Rx 5 Bits/Character */
+#define Rx7 0x40 /* Rx 7 Bits/Character */
+#define Rx6 0x80 /* Rx 6 Bits/Character */
+#define Rx8 0xc0 /* Rx 8 Bits/Character */
+
+/* Write Register 4 */
+
+#define PAR_ENA 0x1 /* Parity Enable */
+#define PAR_EVEN 0x2 /* Parity Even/Odd* */
+
+#define SYNC_ENAB 0 /* Sync Modes Enable */
+#define SB1 0x4 /* 1 stop bit/char */
+#define SB15 0x8 /* 1.5 stop bits/char */
+#define SB2 0xc /* 2 stop bits/char */
+
+#define MONSYNC 0 /* 8 Bit Sync character */
+#define BISYNC 0x10 /* 16 bit sync character */
+#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
+#define EXTSYNC 0x30 /* External Sync Mode */
+
+#define X1CLK 0x0 /* x1 clock mode */
+#define X16CLK 0x40 /* x16 clock mode */
+#define X32CLK 0x80 /* x32 clock mode */
+#define X64CLK 0xC0 /* x64 clock mode */
+
+/* Write Register 5 */
+
+#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
+#define RTS 0x2 /* RTS */
+#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
+#define TxENAB 0x8 /* Tx Enable */
+#define SND_BRK 0x10 /* Send Break */
+#define Tx5 0x0 /* Tx 5 bits (or less)/character */
+#define Tx7 0x20 /* Tx 7 bits/character */
+#define Tx6 0x40 /* Tx 6 bits/character */
+#define Tx8 0x60 /* Tx 8 bits/character */
+#define DTR 0x80 /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define VIS 1 /* Vector Includes Status */
+#define NV 2 /* No Vector */
+#define DLC 4 /* Disable Lower Chain */
+#define MIE 8 /* Master Interrupt Enable */
+#define STATHI 0x10 /* Status high */
+#define NORESET 0 /* No reset on write to R9 */
+#define CHRB 0x40 /* Reset channel B */
+#define CHRA 0x80 /* Reset channel A */
+#define FHWRES 0xc0 /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define BIT6 1 /* 6 bit/8bit sync */
+#define LOOPMODE 2 /* SDLC Loop mode */
+#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
+#define MARKIDLE 8 /* Mark/flag on idle */
+#define GAOP 0x10 /* Go active on poll */
+#define NRZ 0 /* NRZ mode */
+#define NRZI 0x20 /* NRZI mode */
+#define FM1 0x40 /* FM1 (transition = 1) */
+#define FM0 0x60 /* FM0 (transition = 0) */
+#define CRCPS 0x80 /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define TRxCXT 0 /* TRxC = Xtal output */
+#define TRxCTC 1 /* TRxC = Transmit clock */
+#define TRxCBR 2 /* TRxC = BR Generator Output */
+#define TRxCDP 3 /* TRxC = DPLL output */
+#define TRxCOI 4 /* TRxC O/I */
+#define TCRTxCP 0 /* Transmit clock = RTxC pin */
+#define TCTRxCP 8 /* Transmit clock = TRxC pin */
+#define TCBR 0x10 /* Transmit clock = BR Generator output */
+#define TCDPLL 0x18 /* Transmit clock = DPLL output */
+#define RCRTxCP 0 /* Receive clock = RTxC pin */
+#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
+#define RCBR 0x40 /* Receive clock = BR Generator output */
+#define RCDPLL 0x60 /* Receive clock = DPLL output */
+#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define BRENABL 1 /* Baud rate generator enable */
+#define BRSRC 2 /* Baud rate generator source */
+#define DTRREQ 4 /* DTR/Request function */
+#define AUTOECHO 8 /* Auto Echo */
+#define LOOPBAK 0x10 /* Local loopback */
+#define SEARCH 0x20 /* Enter search mode */
+#define RMC 0x40 /* Reset missing clock */
+#define DISDPLL 0x60 /* Disable DPLL */
+#define SSBR 0x80 /* Set DPLL source = BR generator */
+#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
+#define SFMM 0xc0 /* Set FM mode */
+#define SNRZI 0xe0 /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define ZCIE 2 /* Zero count IE */
+#define DCDIE 8 /* DCD IE */
+#define SYNCIE 0x10 /* Sync/hunt IE */
+#define CTSIE 0x20 /* CTS IE */
+#define TxUIE 0x40 /* Tx Underrun/EOM IE */
+#define BRKIE 0x80 /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define Rx_CH_AV 0x1 /* Rx Character Available */
+#define ZCOUNT 0x2 /* Zero count */
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+#define DCD 0x8 /* DCD */
+#define SYNC_HUNT 0x10 /* Sync/hunt */
+#define CTS 0x20 /* CTS */
+#define TxEOM 0x40 /* Tx underrun */
+#define BRK_ABRT 0x80 /* Break/Abort */
+
+/* Read Register 1 */
+#define ALL_SNT 0x1 /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define RES3 0x8 /* 0/3 */
+#define RES4 0x4 /* 0/4 */
+#define RES5 0xc /* 0/5 */
+#define RES6 0x2 /* 0/6 */
+#define RES7 0xa /* 0/7 */
+#define RES8 0x6 /* 0/8 */
+#define RES18 0xe /* 1/8 */
+#define RES28 0x0 /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define PAR_ERR 0x10 /* Parity error */
+#define Rx_OVR 0x20 /* Rx Overrun Error */
+#define CRC_ERR 0x40 /* CRC/Framing Error */
+#define END_FR 0x80 /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
+#define CHBTxIP 0x2 /* Channel B Tx IP */
+#define CHBRxIP 0x4 /* Channel B Rx IP */
+#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
+#define CHATxIP 0x10 /* Channel A Tx IP */
+#define CHARxIP 0x20 /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10 (misc status bits) */
+#define ONLOOP 2 /* On loop */
+#define LOOPSEND 0x10 /* Loop sending */
+#define CLK2MIS 0x40 /* Two clocks missing */
+#define CLK1MIS 0x80 /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc inlines */
+extern inline void ZS_CLEARERR(struct sgi_zschannel *channel)
+{
+ volatile unsigned char junk;
+
+ udelay(2);
+ channel->control = ERR_RES;
+ junk = ioc_icontrol->istat0;
+}
+
+extern inline void ZS_CLEARFIFO(struct sgi_zschannel *channel)
+{
+ volatile unsigned char junk;
+
+ udelay(2);
+ junk = channel->data;
+ udelay(2); junk = ioc_icontrol->istat0;
+ junk = channel->data;
+ udelay(2); junk = ioc_icontrol->istat0;
+ junk = channel->data;
+ udelay(2); junk = ioc_icontrol->istat0;
+}
+
+#if 0
+
+#define ZS_CLEARERR(channel) (channel->control = ERR_RES)
+#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
+ garbage = channel->data; \
+ udelay(2); \
+ garbage = channel->data; \
+ udelay(2); \
+ garbage = channel->data; \
+ udelay(2); } while(0)
+
+#endif
+
+#endif /* !(_SPARC_SERIAL_H) */
diff --git a/drivers/sound/.cvsignore b/drivers/sound/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/drivers/sound/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/.cvsignore b/fs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/affs/.cvsignore b/fs/affs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/affs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 689c52f0d..9af62dafc 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -37,6 +37,8 @@
#include <linux/elf.h>
+#undef DEBUG_ELF
+
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_elf_library(int fd);
extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
@@ -63,6 +65,27 @@ static struct linux_binfmt elf_format = {
#endif
};
+#ifdef DEBUG_ELF
+/* Debugging routines. */
+static void print_elf_p_type(Elf32_Word p_type)
+{
+ int i = (int) p_type;
+
+ switch(i) {
+ case PT_NULL: printk("<PT_NULL> "); break;
+ case PT_LOAD: printk("<PT_LOAD> "); break;
+ case PT_DYNAMIC: printk("<PT_DYNAMIC> "); break;
+ case PT_INTERP: printk("<PT_INTERP> "); break;
+ case PT_NOTE: printk("<PT_NOTE> "); break;
+ case PT_SHLIB: printk("<PT_SHLIB> "); break;
+ case PT_PHDR: printk("<PT_PHDR> "); break;
+ case PT_LOPROC: printk("<PT_LOPROC/REGINFO> "); break;
+ case PT_HIPROC: printk("<PT_HIPROC> "); break;
+ default: printk("<whee %08lx> ", (unsigned long) i); break;
+ }
+}
+#endif /* (DEBUG_ELF) */
+
static void set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
@@ -99,11 +122,23 @@ unsigned long * create_elf_tables(char *p, int argc, int envc,
{
char **argv, **envp;
unsigned long *sp;
+#ifdef __mips__
+ unsigned long * csp;
+#endif
/*
* Force 16 byte alignment here for generality.
*/
sp = (unsigned long *) (~15UL & (unsigned long) p);
+#ifdef __mips__
+ /* 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--;
+#endif
/*
* Put the ELF interpreter info on the stack
@@ -171,7 +206,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
struct file * file;
struct elf_phdr *elf_phdata = NULL;
struct elf_phdr *eppnt;
- unsigned long load_addr, load_off;
+ unsigned long load_addr;
int load_addr_set = 0;
int elf_exec_fileno;
int retval;
@@ -181,14 +216,21 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
elf_bss = 0;
last_bss = 0;
- error = load_off = load_addr = 0;
+ error = load_addr = 0;
+#ifdef DEBUG_ELF
+ printk("[load_elf_interp] ");
+#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)){
+#ifdef DEBUG_ELF
+ printk("bad e_type %d ", interp_elf_ex->e_type);
+#endif
return ~0UL;
}
@@ -253,7 +295,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
}
error = do_mmap(file,
- ELF_PAGESTART(vaddr) + load_off,
+ load_addr + ELF_PAGESTART(vaddr),
eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr),
elf_prot,
elf_type,
@@ -266,24 +308,21 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
return ~0UL;
}
- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
- load_off = error - ELF_PAGESTART(vaddr);
- load_addr = error;
- load_addr_set = 1;
- }
+ if (!load_addr && interp_elf_ex->e_type == ET_DYN)
+ load_addr = (vaddr & 0xfffff000) - error;
/*
* Find the end of the file mapping for this phdr, and keep
* track of the largest address we see for this.
*/
- k = load_off + eppnt->p_vaddr + eppnt->p_filesz;
+ k = load_addr + 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 = load_off + eppnt->p_memsz + eppnt->p_vaddr;
+ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
if (k > last_bss) last_bss = k;
}
@@ -308,7 +347,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
kfree(elf_phdata);
*interp_load_addr = load_addr;
- return ((unsigned long) interp_elf_ex->e_entry) + load_off;
+ return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
}
static unsigned long load_aout_interp(struct exec * interp_ex,
@@ -405,8 +444,13 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return -ENOEXEC;
}
+#ifdef __mips__
+ /* IRIX binaries handled elsewhere. */
+ if(elf_ex.e_flags & EF_MIPS_ARCH)
+ return -ENOEXEC;
+#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) {
@@ -475,8 +519,13 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
#if 0
printk("Using ELF interpreter %s\n", elf_interpreter);
#endif
- if (retval >= 0)
- retval = knamei(elf_interpreter, &interpreter_inode);
+ if (retval >= 0) {
+ old_fs = get_fs(); /* This could probably be optimized */
+ set_fs(get_ds());
+ retval = open_namei(elf_interpreter, 0, 0,
+ &interpreter_inode, NULL);
+ set_fs(old_fs);
+ }
if (retval >= 0)
retval = read_exec(interpreter_inode,0,bprm->buf,128, 1);
@@ -529,7 +578,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
sprintf(passed_fileno, "%d", elf_exec_fileno);
passed_p = passed_fileno;
- if (elf_interpreter) {
+ if(elf_interpreter) {
bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
bprm->argc++;
}
@@ -677,7 +726,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
padzero(elf_bss);
-#if 0
+#ifdef DEBUG_ELF
printk("(start_brk) %x\n" , current->mm->start_brk);
printk("(end_code) %x\n" , current->mm->end_code);
printk("(start_code) %x\n" , current->mm->start_code);
diff --git a/fs/exec.c b/fs/exec.c
index 421300b05..878c65dd6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -67,6 +67,10 @@ void binfmt_setup(void)
init_elf_binfmt();
#endif
+#ifdef CONFIG_BINFMT_IRIX
+ init_irix_binfmt();
+#endif
+
#ifdef CONFIG_BINFMT_AOUT
init_aout_binfmt();
#endif
@@ -399,7 +403,7 @@ static inline void flush_old_signals(struct signal_struct *sig)
struct sigaction * sa = sig->action;
for (i=32 ; i != 0 ; i--) {
- u_sigemptyset(&current->sig->action[i].sa_mask);
+ u_sigemptyset(&sa->sa_mask);
sa->sa_flags = 0;
if (sa->sa_handler != SIG_IGN)
sa->sa_handler = NULL;
@@ -454,8 +458,9 @@ void flush_old_exec(struct linux_binprm * bprm)
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
permission(bprm->inode,MAY_READ))
current->dumpable = 0;
- flush_old_signals(current->sig);
- flush_old_files(current->files);
+
+ flush_old_signals(current->sig);
+ flush_old_files(current->files);
}
/*
diff --git a/fs/ext/.cvsignore b/fs/ext/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/ext/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/ext2/.cvsignore b/fs/ext2/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/ext2/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/fat/.cvsignore b/fs/fat/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/fat/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 55d91ba2b..311907407 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -3,8 +3,6 @@
*
* Written 1992,1993 by Werner Almesberger
* VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
- *
- * 3 May 1996 Fixed alignment problems for RISC architectures.
*/
#define __NO_VERSION__
@@ -246,7 +244,6 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
/* don't divide by zero */
- logical_sector_size = b->sector_size[0] | (b->sector_size[1] << 8);
logical_sector_size =
CF_LE_W(get_unaligned((unsigned short *) &b->sector_size));
sector_mult = logical_sector_size >> SECTOR_BITS;
@@ -261,9 +258,6 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE((
MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
sector_mult);
- data_sectors = ((b->sectors[0] | (b->sectors[1] << 8)) ?
- (b->sectors[0] | (b->sectors[1] << 8)) :
- CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start;
data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors));
if (!data_sectors) {
data_sectors = CF_LE_L(b->total_sect);
@@ -304,7 +298,7 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->fat_length,
MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
MSDOS_SB(sb)->data_start,
- (b->sectors[0] | (b->sectors[1] << 8)),
+ CF_LE_W(*(unsigned short *) &b->sectors),
(unsigned long)b->total_sect,logical_sector_size);
printk ("Transaction block size = %d\n",blksize);
}
diff --git a/fs/hpfs/.cvsignore b/fs/hpfs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/hpfs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/inode.c b/fs/inode.c
index a304b55c9..724e8c4cd 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -422,8 +422,7 @@ void iput(struct inode * inode)
if (!inode->i_count) {
printk("VFS: iput: trying to free free inode\n");
printk("VFS: device %s, inode %lu, mode=0%07o\n",
- kdevname(inode->i_rdev), inode->i_ino,
- (unsigned int) inode->i_mode);
+ kdevname(inode->i_rdev), inode->i_ino, (int) inode->i_mode);
return;
}
if (inode->i_pipe)
diff --git a/fs/isofs/.cvsignore b/fs/isofs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/isofs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/minix/.cvsignore b/fs/minix/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/minix/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/msdos/.cvsignore b/fs/msdos/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/msdos/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/namei.c b/fs/namei.c
index a50881bc8..2b456c72f 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -240,8 +240,8 @@ static int dir_namei(const char *pathname, int *namelen, const char **name,
return 0;
}
-int _namei(const char * pathname, struct inode * base,
- int follow_links, struct inode ** res_inode)
+static int _namei(const char * pathname, struct inode * base,
+ int follow_links, struct inode ** res_inode)
{
const char *basename;
int namelen,error;
@@ -313,8 +313,13 @@ int namei(const char *pathname, struct inode **res_inode)
* which is a lot more logical, and also allows the "no perm" needed
* for symlinks (where the permissions are checked later).
*/
+#ifdef __mips__
+int do_open_namei(const char * pathname, int flag, int mode,
+ struct inode ** res_inode, struct inode * base)
+#else
int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode, struct inode * base)
+#endif
{
const char * basename;
int namelen,error;
diff --git a/fs/ncpfs/.cvsignore b/fs/ncpfs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/ncpfs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/nfs/.cvsignore b/fs/nfs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/nfs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index de77a5a6c..5ec19b0c2 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -118,7 +118,7 @@ static long nfs_file_write(struct inode *inode, struct file *file,
}
if (!S_ISREG(inode->i_mode)) {
printk("nfs_file_write: write to non-file, mode %07o\n",
- (unsigned int) inode->i_mode);
+ (unsigned int) inode->i_mode);
return -EINVAL;
}
if (count == 0)
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index c72685800..2f12cae9b 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -72,7 +72,6 @@
#include <linux/fcntl.h>
#include <asm/param.h>
-#include <asm/segment.h>
#include <linux/utsname.h>
#include <linux/in.h>
#include <linux/if.h>
diff --git a/fs/nfs/sock.c b/fs/nfs/sock.c
index 745a33639..6191cfeb3 100644
--- a/fs/nfs/sock.c
+++ b/fs/nfs/sock.c
@@ -102,9 +102,17 @@ nfs_rpc_doio(struct nfs_server *server, struct rpc_ioreq *req, int async)
break;
}
if (!major_timeout_seen) {
+#if defined(CONFIG_SGISEEQ) && 1
+ extern void sgiseeq_dump_rings(void);
+ extern void sgiseeq_my_reset(void);
+#endif
printk("NFS server %s not responding, "
"still trying.\n", server->hostname);
major_timeout_seen = 1;
+#if defined(CONFIG_SGISEEQ) && 1
+ sgiseeq_dump_rings();
+ sgiseeq_my_reset();
+#endif
}
if ((timeout.to_initval <<= 1) >= maxtimeo) {
timeout.to_initval = maxtimeo;
diff --git a/fs/proc/.cvsignore b/fs/proc/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/proc/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f0bf55221..20cac345a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -408,9 +408,6 @@ static int get_arg(int pid, char * buffer)
return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
}
-#ifdef __mips__
-extern unsigned long (*get_wchan)(struct task_struct *p);
-#else
static unsigned long get_wchan(struct task_struct *p)
{
if (!p || p == current || p->state == TASK_RUNNING)
@@ -456,11 +453,25 @@ static unsigned long get_wchan(struct task_struct *p)
}
return pc;
}
+#elif defined(__mips__)
+ /*
+ * The same comment as on the Alpha applies here, too ...
+ */
+ {
+ unsigned long schedule_frame;
+ unsigned long pc;
+
+ pc = thread_saved_pc(&p->tss);
+ if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+ schedule_frame = ((unsigned long *)(long)p->tss.reg30)[15];
+ return (unsigned long)((unsigned long *)schedule_frame)[11];
+ }
+ return pc;
+ }
#endif
return 0;
}
-#endif
#if defined(__i386__)
# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
diff --git a/fs/smbfs/.cvsignore b/fs/smbfs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/smbfs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/sysv/.cvsignore b/fs/sysv/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/sysv/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/ufs/.cvsignore b/fs/ufs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/ufs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/umsdos/.cvsignore b/fs/umsdos/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/umsdos/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/vfat/.cvsignore b/fs/vfat/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/vfat/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/fs/xiafs/.cvsignore b/fs/xiafs/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/fs/xiafs/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h
index f5eae6ee2..b9471de7b 100644
--- a/include/asm-alpha/floppy.h
+++ b/include/asm-alpha/floppy.h
@@ -13,7 +13,7 @@
#include <linux/config.h>
#define fd_inb(port) inb_p(port)
-#define fd_outb(value,port) outb_p(value,port)
+#define fd_outb(port,value) outb_p(port,value)
#define fd_enable_dma() enable_dma(FLOPPY_DMA)
#define fd_disable_dma() disable_dma(FLOPPY_DMA)
diff --git a/include/asm-alpha/keyboard.h b/include/asm-alpha/keyboard.h
index 6aca53255..1ffbeef53 100644
--- a/include/asm-alpha/keyboard.h
+++ b/include/asm-alpha/keyboard.h
@@ -12,6 +12,8 @@
#define KEYBOARD_IRQ 1
+#define KBD_REPORT_ERR
+
static int initialize_kbd(void);
#define kbd_inb_p(port) inb_p(port)
diff --git a/include/asm-alpha/mc146818rtc.h b/include/asm-alpha/mc146818rtc.h
deleted file mode 100644
index 40ce6163f..000000000
--- a/include/asm-alpha/mc146818rtc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Machine dependend access functions for RTC registers.
- */
-#ifndef __ASM_ALPHA_MC146818RTC_H
-#define __ASM_ALPHA_MC146818RTC_H
-
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ALWAYS_BCD 1
-#endif
-
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-#endif /* __ASM_ALPHA_MC146818RTC_H */
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index 9e4f2d595..e2b61494a 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -107,8 +107,6 @@ typedef unsigned long pgprot_t;
#endif
-#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE)
-
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index 9854413fd..db9c62a7d 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -172,11 +172,6 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int
return x;
}
-/*
- * Reset the machine.
- */
-extern void hard_reset_now(void);
-
#endif /* __ASSEMBLY__ */
#endif
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
new file mode 100644
index 000000000..130619840
--- /dev/null
+++ b/include/asm-generic/bitops.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_BITOPS_H_
+#define _ASM_GENERIC_BITOPS_H_
+
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents. You should
+ * recode these in the native assembly language, if at all possible.
+ * To guarantee atomicity, these routines call cli() and sti() to
+ * disable interrupts while they operate. (You have to provide inline
+ * routines to cli() and sti().)
+ *
+ * Also note, these routines assume that you have 32 bit integers.
+ * You will have to change this if you are trying to port Linux to the
+ * Alpha architecture or to a Cray. :-)
+ *
+ * C language equivalents written by Theodore Ts'o, 9/26/92
+ */
+
+extern __inline__ int set_bit(int nr,int * addr)
+{
+ int mask, retval;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ cli();
+ retval = (mask & *addr) != 0;
+ *addr |= mask;
+ sti();
+ return retval;
+}
+
+extern __inline__ int clear_bit(int nr, int * addr)
+{
+ int mask, retval;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ cli();
+ retval = (mask & *addr) != 0;
+ *addr &= ~mask;
+ sti();
+ return retval;
+}
+
+extern __inline__ int test_bit(int nr, int * addr)
+{
+ int mask;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ return ((mask & *addr) != 0);
+}
+#endif /* _ASM_GENERIC_BITOPS_H */
diff --git a/include/asm-i386/keyboard.h b/include/asm-i386/keyboard.h
index 76fa2186c..ed6c7d472 100644
--- a/include/asm-i386/keyboard.h
+++ b/include/asm-i386/keyboard.h
@@ -12,6 +12,8 @@
#define KEYBOARD_IRQ 1
+#define KBD_REPORT_ERR
+
#define kbd_inb_p(port) inb_p(port)
#define kbd_inb(port) inb(port)
#define kbd_outb_p(data,port) outb_p(data,port)
diff --git a/include/asm-i386/mc146818rtc.h b/include/asm-i386/mc146818rtc.h
deleted file mode 100644
index 594996a6d..000000000
--- a/include/asm-i386/mc146818rtc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Machine dependend access functions for RTC registers.
- */
-#ifndef __ASM_I386_MC146818RTC_H
-#define __ASM_I386_MC146818RTC_H
-
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ALWAYS_BCD 1
-#endif
-
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-#endif /* __ASM_I386_MC146818RTC_H */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index e5fc37276..4744df9c8 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -53,20 +53,6 @@ typedef unsigned long pgprot_t;
#endif
-/*
- * We special-case the C-O-W ZERO_PAGE, because it's such
- * a common occurrence (no need to read the page to know
- * that it's zero - better for the cache and memory subsystem).
- */
-extern inline inline void copy_page(unsigned long from, unsigned long to)
-{
- if (from == ZERO_PAGE) {
- memset((void *) to, 0, PAGE_SIZE);
- return;
- }
- memcpy((void *) to, (void *) from, PAGE_SIZE);
-}
-
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
diff --git a/include/asm-i386/slots.h b/include/asm-i386/slots.h
deleted file mode 100644
index 21139c59c..000000000
--- a/include/asm-i386/slots.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-i386/slots.h
- *
- * Written by Ralf Baechle
- * Copyright (C) 1994 by Waldorf GMBH
- */
-#ifndef _ASM_I386_SLOTS_H
-#define _ASM_I386_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 0x0
-
-#endif /* _ASM_I386_SLOTS_H */
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index ae8c56a96..cef63f6fe 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -298,9 +298,4 @@ extern struct desc_struct default_ldt;
void disable_hlt(void);
void enable_hlt(void);
-/*
- * Reset the machine.
- */
-extern void hard_reset_now(void);
-
#endif
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index 859c748e3..58c8d3905 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -145,9 +145,4 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
}
#endif
-/*
- * Reset the machine.
- */
-extern void hard_reset_now(void);
-
#endif /* _M68K_SYSTEM_H */
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h
index afb189d63..20dd39cb6 100644
--- a/include/asm-mips/asm.h
+++ b/include/asm-mips/asm.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*
* Some useful macros for MIPS assembler code
*
@@ -131,23 +131,6 @@ symbol = value
.text
/*
- * Return from exception
- */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-#define ERET rfe
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
-#define ERET \
- eret; \
- nop; \
- nop; \
- nop; \
- nop; \
- nop
-#endif
-
-/*
* MIPS IV pref instruction.
* Use with .set noreorder only!
*
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
new file mode 100644
index 000000000..e48f759ca
--- /dev/null
+++ b/include/asm-mips/asmmacro.h
@@ -0,0 +1,115 @@
+/* $Id: asmmacro.h,v 1.4 1996/06/29 12:41:13 dm 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/bitops.h b/include/asm-mips/bitops.h
index 4a7f8ab89..53de94227 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -10,7 +10,25 @@
#ifndef __ASM_MIPS_BITOPS_H
#define __ASM_MIPS_BITOPS_H
+#ifdef __KERNEL__
+
#include <asm/sgidefs.h>
+#include <asm/system.h>
+
+/*
+ * 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)
+#else
+#define __flags
+#define __cli()
+#define __save_flags(x)
+#define __restore_flags(x)
+#endif /* __KERNEL__ */
/*
* Note that the bit operations are defined on arrays of 32 bit sized
@@ -21,7 +39,9 @@ extern __inline__ int set_bit(int nr, void *addr);
extern __inline__ int clear_bit(int nr, void *addr);
extern __inline__ int 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);
@@ -46,8 +66,7 @@ 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;
}
@@ -76,37 +95,13 @@ 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 I */
-#ifdef __KERNEL__
-/*
- * 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>
-
-/*
- * 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)
-#else
-#define __flags
-#define __cli()
-#define __save_flags(x)
-#define __restore_flags(x)
-#endif /* __KERNEL__ */
-
extern __inline__ int set_bit(int nr, void * addr)
{
int mask, retval;
@@ -170,6 +165,10 @@ extern __inline__ int test_bit(int nr, const void *addr)
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;
@@ -259,6 +258,8 @@ extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
return offset + set + res;
}
+#endif /* !(__MIPSEB__) */
+
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
@@ -287,17 +288,167 @@ extern __inline__ unsigned long ffz(unsigned long word)
return __res;
}
-#ifdef __KERNEL__
#ifdef __MIPSEB__
-#error "Aieee... fix these sources for big endian machines"
-#endif /* __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.
+ */
-#define ext2_set_bit set_bit
-#define ext2_clear_bit clear_bit
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
+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;
-#endif /* __KERNEL__ */
+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) set_bit((nr), (addr))
+#define ext2_clear_bit(nr, addr) 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))
+#endif
#endif /* __ASM_MIPS_BITOPS_H */
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index a7e712b96..7388b34d0 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -11,16 +11,41 @@
#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
+
/*
- * Valid machgroup values
+ * Values for machgroup
*/
-#define MACH_GROUP_UNKNOWN 0 /* whatever... */
-#define MACH_GROUP_JAZZ 1 /* Acer Pica 61, Mips Magnum 4000, Olivetti */
- /* M700-10 */
-#define MACH_GROUP_DEC 2 /* Digital */
-#define MACH_GROUP_ARC 3 /* Deskstation Tyne, rpc44, possibly other */
-#define MACH_GROUP_SNI_RM 4 /* Siemens Nixdorf RM series */
+#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" }
@@ -58,20 +83,25 @@
#define GROUP_ARC_NAMES { "Deskstation rPC44", "Deskstation Tyne" }
/*
- * Valid machtype for group SNI_RM
+ * 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 SNI_RM
+ * Valid machtype for group ACN
*/
-#define MACH_ACN_MIPS_BOARD 0 /* ACN MIPS single board */
+#define MACH_ACN_MIPS_BOARD 0 /* ACN MIPS single board */
#define GROUP_ACN_NAMES { "ACN" }
/*
+ * Valid machtype for group SGI
+ */
+#define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstaions */
+
+/*
* Valid cputype values
*/
#define CPU_UNKNOWN 0
@@ -101,7 +131,7 @@
#define CPU_R5000 24
#define CPU_R5000A 25
#define CPU_R4640 26
-#define CPU_LAST 26
+#define CPU_LAST 27
#define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \
"R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC", \
@@ -123,12 +153,11 @@ struct drive_info_struct {
/* 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;
+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;
/*
@@ -136,8 +165,6 @@ typedef struct mips_arc_DisplayInfo /* video adapter information */
*
* Add new tags only at the end of the enum; *never* remove any tags
* or you'll break compatibility!
- * Which compatibility ? compatibility consideration lead to
- * MS-DOG :) -Stoned
*/
enum bi_tag {
/*
@@ -191,8 +218,7 @@ enum bi_tag {
/*
* Boot flags for the kernel
*/
- tag_mount_root_rdonly, /* No longer used; use "ro" command
- line argument instead. */
+ tag_mount_root_rdonly,
tag_drive_info,
/*
@@ -216,7 +242,6 @@ enum bi_tag {
* tag to pass a complete struct screen_info
*/
tag_screen_info
-
};
/* struct defining a tag */
@@ -242,7 +267,9 @@ typedef struct {
#define DRVINFOSIZE (sizeof(struct drive_info_struct))
#define CMDLINESIZE (sizeof(char[CL_SIZE])
-/* For tag readers aka the kernel */
+/*
+ * For tag readers aka the kernel
+ */
tag *bi_TagFind(enum bi_tag type);
void bi_EarlySnarf(void);
@@ -252,11 +279,22 @@ int bi_TagAdd(enum bi_tag type, unsigned long size, void *data);
int bi_TagAddList(tag_def* taglist);
void bi_TagWalk(void);
+
+#ifdef CONFIG_SGI
+
+/* screen info will dissapear... soon */
+#define DEFAULT_SCREEN_INFO {0, 0, {0, 0, }, 0, 0, 158, 0, 0, 0, 62, 0, 16}
+
+#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
+
+
/*
* These are the kernel variables initialized from
* the tag. And they have to be initialized to dummy/default
diff --git a/include/asm-mips/branch.h b/include/asm-mips/branch.h
index abca807ec..08dda213e 100644
--- a/include/asm-mips/branch.h
+++ b/include/asm-mips/branch.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 1997 by Ralf Baechle
*/
#include <asm/ptrace.h>
diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h
index bf4c54a1f..92e3b8863 100644
--- a/include/asm-mips/byteorder.h
+++ b/include/asm-mips/byteorder.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*/
#ifndef __ASM_MIPS_BYTEORDER_H
#define __ASM_MIPS_BYTEORDER_H
diff --git a/include/asm-mips/cache.h b/include/asm-mips/cacheops.h
index 7add64caa..66b0b361f 100644
--- a/include/asm-mips/cache.h
+++ b/include/asm-mips/cacheops.h
@@ -1,14 +1,14 @@
/*
- * Defines related to MIPS caches.
+ * 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 by Ralf Baechle
+ * (C) Copyright 1996, 1997 by Ralf Baechle
*/
-#ifndef __ASM_MIPS_CACHE
-#define __ASM_MIPS_CACHE
+#ifndef __ASM_MIPS_CACHEOPS_H
+#define __ASM_MIPS_CACHEOPS_H
/*
* Cache Operations
@@ -44,24 +44,4 @@
#define Hit_Set_Virtual_SI 0x1e
#define Hit_Set_Virtual_SD 0x1f
-/*
- * Flags for internal cacheflush call
- * FIXME: CF_DMA is not implemented yet.
- */
-#define CF_ICACHE (1<<0) /* flush instruction cache */
-#define CF_DCACHE (1<<1) /* writeback and flush data cache */
-#define CF_BCACHE (CF_ICACHE|CF_DCACHE) /* writeback and flush data cache */
-#define CF_VIRTUAL (1<<2) /* operate only on virtual caches */
-#define CF_PHYSICAL (1<<4) /* operate only on physical caches */
-#define CF_ALL (CF_VIRTUAL|CF_PHYSICAL)/* work on all cache types */
-#define CF_DMA (1<<5) /* Do DMA cache maintenance */
-
-#ifndef __LANGUAGE_ASSEMBLY__
-
-#include <linux/linkage.h>
-
-extern void (*mips_cache_init)(void);
-extern asmlinkage void (*cacheflush)(unsigned long addr, unsigned long nbytes, unsigned int flags);
-
-#endif /* !__LANGUAGE_ASSEMBLY__ */
-#endif /* __ASM_MIPS_CACHE */
+#endif /* __ASM_MIPS_CACHEOPS_H */
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index 08dd07707..f6423ecce 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -148,7 +148,13 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
nor %0,$0,%0
.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;
@@ -185,7 +191,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
unsigned short proto,
unsigned int sum)
{
- __asm__("
+ __asm__("
.set noreorder
.set noat
addu %0,%5 # proto (long in network byte order)
@@ -234,13 +240,12 @@ 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),
+ .set noreorder"
+ : "=r" (sum),
"=r" (proto)
- : "r" (saddr),
+ : "r" (saddr),
"r" (daddr),
- "0" (htonl((__u32) (len))),
+ "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
index 000000000..b93af21c8
--- /dev/null
+++ b/include/asm-mips/cpu.h
@@ -0,0 +1,36 @@
+/* $Id: cpu.h,v 1.1 1996/06/23 09:38:33 dm 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
+#define PRID_IMP_R5000 0x2300
+#define PRID_IMP_SONIC 0x2400
+#define PRID_IMP_UNKNOWN 0xff00
+
+#define PRID_REV_R4400 0x0040
+#define PRID_REV_R3000A 0x0030
+#define PRID_REV_R3000 0x0020
+#define PRID_REV_R2000A 0x0010
+
+#endif /* !(_MIPS_CPU_H) */
diff --git a/include/asm-mips/dec/decstation.h b/include/asm-mips/dec/decstation.h
deleted file mode 100644
index cae4302d2..000000000
--- a/include/asm-mips/dec/decstation.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * General info common to all DECstation systems
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
- * are by curteousy of Chris Fraser.
- *
- * This file is under construction - you were warned!
- */
-
-#ifndef __ASM_DEC_DECSTATION_H
-#define __ASM_DEC_DECSTATION_H
-
-/*
- * 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 */
-#define REX_GETENV 0x64 /* get env. variable */
-#define REX_GETSYSID 0x80 /* get system id */
-#define REX_OPEN 0x54 /* open() */
-#define REX_READ 0x58 /* read() */
-
-
-
-#ifndef __LANGUAGE_ASSEMBLY__
-
-/*
- * A structure to allow calling of the various DEC boot prom routines.
- * FIXME: Don't know how well different DECStation boot prom revisions
- * are accomodated.
- */
-struct dec_prom {
- void (*dec_prom_printf)(char *format, ...);
- char *(*dec_prom_getenv)(char *name);
- unsigned long (*dec_prom_getbitmap)(void);
- unsigned long (*dec_prom_getsysid)(void);
- char *(*dec_prom_gets)(char *s);
- void (*dec_prom_halt)(const unsigned int);
-};
-
-#endif
-
-#endif /* __ASM_DEC_DECSTATION_H */
diff --git a/include/asm-mips/dec/kn02.h b/include/asm-mips/dec/kn02.h
deleted file mode 100644
index 61df7b512..000000000
--- a/include/asm-mips/dec/kn02.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Hardware info about DEC DECstation 5000/2xx systems (otherwise known
- * as 3max or kn02.
- *
- * 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 Paul M. Antoine, some code and definitions
- * are by curteousy of Chris Fraser.
- *
- * This file is under construction - you were warned!
- */
-#include <asm/segment.h>
-#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 KSEG1ADDR(0x1ff00000) /* system control & status reg */
-
-/*
- * SSR defines
- */
-#define PMAX_SSR_LEDMASK 0x0000001000 /* diagnostic LED */
-
-#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;
-}
-
-#endif
-
-/*
- * Some port addresses...
- * FIXME: these addresses are incomplete and need tidying up!
- */
-#define PMAX_RTC_BASE (KSEG1ADDR(0x1fe80000 + 0x200000)) /* ASIC + SL8 */
-
-#endif /* __ASM_MIPS_PMAX_H */
diff --git a/include/asm-mips/dec/maxine.h b/include/asm-mips/dec/maxine.h
deleted file mode 100644
index 3f908d5fb..000000000
--- a/include/asm-mips/dec/maxine.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Hardware info about DEC Personal DECStation systems (otherwise known
- * as maxine (internal DEC codename).
- *
- * 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 Paul M. Antoine, some code and definitions
- * are by curteousy of Chris Fraser.
- *
- * This file is under construction - you were warned!
- */
-
-#ifndef __ASM_DEC_MAXINE_H
-#define __ASM_DEC_MAXINE_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 KSEG1ADDR(0x1c040100) /* system support reg */
-
-/*
- * SSR defines
- */
-#define PMAX_SSR_LEDMASK 0x00000001 /* power LED */
-
-#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;
-}
-
-#endif
-
-/*
- * Some port addresses...
- * FIXME: these addresses are incomplete and need tidying up!
- */
-#define PMAX_RTC_BASE (KSEG1ADDR(0x1c000000 + 0x200000)) /* ASIC + SL8 */
-
-#endif /* __ASM_DEC_MAXINE_H */
diff --git a/include/asm-mips/deskstation.h b/include/asm-mips/deskstation.h
new file mode 100644
index 000000000..52b8cdf43
--- /dev/null
+++ b/include/asm-mips/deskstation.h
@@ -0,0 +1,15 @@
+/*
+ * SNI specific definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_DESKSTATION_H
+#define __ASM_MIPS_DESKSTATION_H
+
+#define RPC44_PORT_BASE 0xe2000000
+
+#endif /* __ASM_MIPS_DESKSTATION_H */
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h
index c3fd31d58..320022c76 100644
--- a/include/asm-mips/dma.h
+++ b/include/asm-mips/dma.h
@@ -12,7 +12,8 @@
#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
@@ -79,7 +80,11 @@
* Deskstations or Acer PICA but not the much more versatile DMA logic used
* for the local devices on Acer PICA or Magnums.
*/
+#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 */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 527352711..97e670510 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -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];
@@ -16,32 +13,31 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
/*
* This is used to ensure we don't load something for the wrong architecture.
- * Using EM_MIPS is actually wrong - this one is reserved for big endian
- * machines only but there is no EM_ constant for little endian ...
*/
#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
#ifdef __MIPSEB__
-#define ELF_DATA ELFDATA2MSB;
+#define ELF_DATA ELFDATA2MSB;
#elif __MIPSEL__
-#define ELF_DATA ELFDATA2LSB;
+#define ELF_DATA ELFDATA2LSB;
#endif
#define ELF_ARCH EM_MIPS
- /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
- starts %edx contains a pointer to a function which might be
- registered using `atexit'. This provides a mean for the
- dynamic linker to call DT_FINI functions for shared libraries
- that have been loaded before the code runs.
-
- A value of 0 tells we have no such handler. */
-#define ELF_PLAT_INIT(_r) _r->regs[2] = 0
-
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
+#define ELF_CORE_COPY_REGS(_dest,_regs) \
+ memcpy((char *) &_dest, (char *) _regs, \
+ sizeof(struct pt_regs));
+
+/* See comments in asm-alpha/elf.h, this is the same thing
+ * on the MIPS.
+ */
+#define ELF_PLAT_INIT(_r) _r->regs[2] = 0;
+
#endif /* __ASM_MIPS_ELF_H */
diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h
index dc4072a94..70b1effd9 100644
--- a/include/asm-mips/errno.h
+++ b/include/asm-mips/errno.h
@@ -65,14 +65,7 @@
#define ENOANO 53 /* No anode */
#define EBADRQC 54 /* Invalid request code */
#define EBADSLT 55 /* Invalid slot */
-#if 0
#define EDEADLOCK 56 /* File locking deadlock error */
-#else
-/*
- * This needs to be fixed - DEADLOCK should be 45.
- */
-#define EDEADLOCK EDEADLK /* File locking deadlock error */
-#endif
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index e6bc9ae3c..b09ca61a4 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -15,7 +15,7 @@
/*
* 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
diff --git a/include/asm-mips/jazz.h b/include/asm-mips/jazz.h
index 9a3dbccf0..2f6e4b225 100644
--- a/include/asm-mips/jazz.h
+++ b/include/asm-mips/jazz.h
@@ -307,8 +307,8 @@ extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val)
#endif /* !LANGUAGE_ASSEMBLY__ */
-#define JAZZ_FDC_BASE 0xe0003000
-
-#define JAZZ_RTC_BASE 0xe0004000
+#define JAZZ_FDC_BASE 0xe0003000
+#define JAZZ_RTC_BASE 0xe0004000
+#define JAZZ_PORT_BASE 0xe2000000
#endif /* __ASM_MIPS_JAZZ_H */
diff --git a/include/asm-mips/keyboard.h b/include/asm-mips/keyboard.h
index 3c5c7ce65..a99289d00 100644
--- a/include/asm-mips/keyboard.h
+++ b/include/asm-mips/keyboard.h
@@ -9,6 +9,7 @@
#define __ASM_MIPS_KEYBOARD_H
#include <linux/config.h>
+#include <linux/delay.h>
/*
* The default IO slowdown is doing 'inb()'s from 0x61, which should be
@@ -19,13 +20,30 @@
#define REALLY_SLOW_IO
#define SLOW_IO_BY_JUMPING
#include <asm/io.h>
+
+#ifdef CONFIG_SGI
+#include <asm/segment.h>
+#include <asm/sgihpc.h>
+#endif
#include <asm/bootinfo.h>
#include <asm/jazz.h>
-/*
- * Not true for Jazz machines, we cheat a bit for 'em.
- */
+#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
static int initialize_kbd(void);
@@ -34,13 +52,21 @@ 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
+#if defined(CONFIG_MIPS_JAZZ) || defined(CONFIG_SGI)
/*
* We want the full initialization for the keyboard controller.
*/
-#define INIT_KBD
+/* XXX Define both and ... */
+#ifdef CONFIG_MIPS_JAZZ
+#define INIT_KBD /* full initialization for the keyboard controller. */
static volatile keyboard_hardware *kh = (void *) JAZZ_KEYBOARD_ADDRESS;
+#endif
+
+#ifdef CONFIG_SGI
+#define INIT_KBD /* full initialization for the keyboard controller. */
+volatile struct hpc_keyb *kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64);
+#endif
static int
jazz_kbd_inb_p(unsigned short port)
@@ -51,7 +77,9 @@ jazz_kbd_inb_p(unsigned short port)
result = kh->data;
else /* Must be KBD_STATUS_REG */
result = kh->command;
+#ifndef CONFIG_SGI
inb(0x80);
+#endif
return result;
}
@@ -76,7 +104,9 @@ jazz_kbd_outb_p(unsigned char data, unsigned short port)
kh->data = data;
else if(port == KBD_CNTL_REG)
kh->command = data;
+#ifndef CONFIG_SGI
inb(0x80);
+#endif
}
static void
diff --git a/include/asm-mips/mipsconfig.h b/include/asm-mips/mipsconfig.h
index 01316c11b..bb9907bc1 100644
--- a/include/asm-mips/mipsconfig.h
+++ b/include/asm-mips/mipsconfig.h
@@ -5,12 +5,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
- *
- * This file contains constant definitions and some MIPS specific debug and
- * other compile time switches.
+ * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle
*/
-
#ifndef __ASM_MIPS_MIPSCONFIG_H
#define __ASM_MIPS_MIPSCONFIG_H
@@ -18,10 +14,6 @@
* This is the virtual address to which all ports are being mapped.
* Must be a value that can be load with a lui instruction.
*/
-#define PORT_BASE_SNI 0xb4000000
-#define PORT_BASE_RPC44 0xe2000000
-#define PORT_BASE_TYNE 0xe2000000
-#define PORT_BASE_JAZZ 0xe2000000
#ifndef PORT_BASE
#if !defined (__LANGUAGE_ASSEMBLY__)
extern unsigned long port_base;
@@ -29,23 +21,10 @@ extern unsigned long port_base;
#define PORT_BASE port_base
#endif
-/*
- * Pagetables are 4MB mapped at 0xe4000000
- * Must be a value that can be loaded with a single instruction.
- * The xtlb exception handler assumes that bit 30 and 31 of TLBMAP
- * are the same. This is true for all KSEG2 and KSEG3 addresses and
- * will therefore not a problem.
- */
-#define TLBMAP 0xe4000000
+/* Pgdir is 1 page mapped at 0xff800000. */
+#define TLBMAP 0xff800000
-/*
- * 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
+/* The virtual address where we'll map the pgdir. */
+#define TLB_ROOT 0xff000000
#endif /* __ASM_MIPS_MIPSCONFIG_H */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 12666127e..bf2340305 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -25,23 +25,6 @@
#endif
/*
- * 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_R3000A 0x02
-#define PRID_R4000 0x04
-#define PRID_R4400 0x04
-#define PRID_R4300 0x0b
-#define PRID_R4600 0x20
-#define PRID_R4700 0x21
-#define PRID_R4640 0x22
-#define PRID_R4650 0x22
-#define PRID_R5000 0x23
-#define PRID_SONIC 0x24
-#define PRID_R10000 0x09
-
-/*
* Coprocessor 0 register names
*/
#define CP0_INDEX $0
@@ -125,6 +108,9 @@
: "=r" (__res)); \
__res;})
+/*
+ * For now use this only with interrupts disabled!
+ */
#define read_64bit_cp0_register(source) \
({ int __res; \
__asm__ __volatile__( \
@@ -233,52 +219,51 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
/*
* Bitfields in the R4xx0 cp0 status register
*/
-#define ST0_IE (1 << 0)
-#define ST0_EXL (1 << 1)
-#define ST0_ERL (1 << 2)
-#define ST0_KSU (3 << 3)
-# define KSU_USER (2 << 3)
-# define KSU_SUPERVISOR (1 << 3)
-# define KSU_KERNEL (0 << 3)
-#define ST0_UX (1 << 5)
-#define ST0_SX (1 << 6)
-#define ST0_KX (1 << 7)
+#define ST0_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_IEC (1 << 0)
-#define ST0_KUC (1 << 1)
-#define ST0_IEP (1 << 2)
-#define ST0_KUP (1 << 3)
-#define ST0_IEO (1 << 4)
-#define ST0_KUO (1 << 5)
+#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)
+#define ST0_UM <1 << 4)
+#define ST0_IL (1 << 23)
+#define ST0_DL (1 << 24)
/*
* Status register bits available in all MIPS CPUs.
*/
-#define ST0_IM (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) /* MIPS IV 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.
@@ -313,9 +298,9 @@ BUILD_SET_CP0(cause,CP0_CAUSE)
/*
* Bits in the coprozessor 0 config register.
*/
-#define CONFIG_DB (1<<4)
-#define CONFIG_IB (1<<5)
-#define CONFIG_SC (1<<17)
+#define CONFIG_DB (1 << 4)
+#define CONFIG_IB (1 << 5)
+#define CONFIG_SC (1 << 17)
/*
* R10000 performance counter definitions.
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 5a61279da..d905d8f11 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -10,13 +10,38 @@
#ifndef __ASM_MIPS_MMU_CONTEXT_H
#define __ASM_MIPS_MMU_CONTEXT_H
-/*
- * Get a new mmu context. For MIPS we use resume() to change the
- * PID (R3000)/ASID (R4000). Well, we will ...
- */
-extern __inline__ void
-get_mmu_context(struct task_struct *p)
+#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);
+ }
}
#endif /* __ASM_MIPS_MMU_CONTEXT_H */
diff --git a/include/asm-mips/offset.h b/include/asm-mips/offset.h
new file mode 100644
index 000000000..c5e6f37fa
--- /dev/null
+++ b/include/asm-mips/offset.h
@@ -0,0 +1,89 @@
+/* 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_PRIORITY 8
+#define TASK_SIGNAL 12
+#define TASK_BLOCKED 16
+#define TASK_FLAGS 20
+#define TASK_SAVED_KSTACK 84
+#define TASK_KSTACK_PG 88
+#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 0
+#define MM_PGD 4
+#define MM_CONTEXT 8
+
+#endif /* !(_MIPS_OFFSET_H) */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 6339c0373..ba42d3baa 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -19,11 +19,11 @@
#define STRICT_MM_TYPECHECKS
+#ifndef __LANGUAGE_ASSEMBLY__
+
extern void (*clear_page)(unsigned long page);
extern void (*copy_page)(unsigned long to, unsigned long from);
-#ifndef __LANGUAGE_ASSEMBLY__
-
#ifdef STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
@@ -69,46 +69,16 @@ typedef unsigned long pgprot_t;
/* 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 0
/*
- * Kernel with 64 bit address space.
- * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent)
- * Pagetables are at XKPHYS + 0x1000000000000000 (uncached)
- */
-#define PAGE_OFFSET 0x9800000000000000UL
-#define PT_OFFSET 0x9000000000000000UL
-#define MAP_MASK 0x07ffffffffffffffUL
-#else /* !defined (__mips64) */
-/*
- * Kernel with 32 bit address space.
- * We handle pages at KSEG0 (cachable, noncoherent)
- * Pagetables are at KSEG1 (uncached)
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
*/
#define PAGE_OFFSET 0x80000000UL
-#define PT_OFFSET 0xa0000000UL
+#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#define MAP_MASK 0x1fffffffUL
-#endif /* !defined (__mips64) */
-
-/*
- * __pa breaks when applied to a pagetable pointer on >= R4000.
- */
-#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
-#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
-
#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/pgtable.h b/include/asm-mips/pgtable.h
index 2744d5c24..2192a39d5 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -1,12 +1,3 @@
-/*
- * Linux/MIPS pagetables
- *
- * 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_PGTABLE_H
#define __ASM_MIPS_PGTABLE_H
@@ -16,100 +7,44 @@
#ifndef __LANGUAGE_ASSEMBLY__
#include <linux/linkage.h>
-#include <asm/cache.h>
-
-extern inline void
-flush_cache_all(void)
-{
- cacheflush(0, ~0UL, CF_DCACHE|CF_VIRTUAL);
-}
-
-extern inline void
-flush_cache_mm(struct mm_struct *mm)
-{
- cacheflush(0, ~0UL, CF_BCACHE|CF_VIRTUAL);
-}
+#include <asm/cachectl.h>
-extern inline void
-flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
- cacheflush(start, end - start, CF_DCACHE|CF_VIRTUAL);
-}
-
-extern inline void
-flush_cache_page(struct vm_area_struct * vma, unsigned long vmaddr)
-{
- unsigned int flags;
-
- flags = (vma->vm_flags & VM_EXEC) ? CF_BCACHE|CF_VIRTUAL
- : CF_DCACHE|CF_VIRTUAL;
- cacheflush(vmaddr, PAGE_SIZE, flags);
-}
-
-extern inline void
-flush_page_to_ram(unsigned long page)
-{
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
-}
-
-/*
- * 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.
+/* Cache flushing:
*
- * This file contains the functions and defines necessary to modify and use
- * the MIPS page table tree. Note the frequent conversion between addresses
- * in KSEG0 and KSEG1.
- *
- * This is required due to the cache aliasing problem of the R4xx0 series.
- * Sometimes doing uncached accesses also to improve the cache performance
- * slightly. The R10000 caching mode "uncached accelerated" will help even
- * further.
+ * - 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:
+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:
*
- * - flush_tlb() flushes the current mm struct TLB entries
* - 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
- *
- * FIXME: MIPS has full control of all TLB activity in the CPU. Though
- * we just stick with complete flushing of TLBs for now.
- * Currently this code only supports only R4000 and newer. Support
- * for R3000 is in the works. The R6000 uses a 2x8 entry TLB slice
- * and the R6000A an 16 entry TLB slice which is quite different
- * from the memory management concepts of the other R-series CPUs.
- * Only a few machines with this CPU still exist and I don't have one
- * so chances for complete R6000 support are relativly low.
*/
-extern asmlinkage void tlbflush(void);
-extern asmlinkage void tlbflush_page(unsigned long addr);
-#define flush_tlb() tlbflush()
-#define flush_tlb_all() flush_tlb()
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- if (mm == current->mm)
- flush_tlb();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
-{
- if (vma->vm_mm == current->mm)
- tlbflush_page(addr);
-}
+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.
+ */
-static inline void flush_tlb_range(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- if (mm == current->mm)
- flush_tlb();
-}
#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
/* PMD_SHIFT determines the size of the area a second-level page table can map */
@@ -122,8 +57,7 @@ static inline void flush_tlb_range(struct mm_struct *mm,
#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
@@ -133,22 +67,32 @@ static inline void flush_tlb_range(struct mm_struct *mm,
#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_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_UNUSED1 (1<<5)
+#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 */
@@ -167,16 +111,15 @@ static inline void flush_tlb_range(struct mm_struct *mm,
#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 | \
+#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)
@@ -206,9 +149,6 @@ static inline void flush_tlb_range(struct mm_struct *mm,
#if !defined (__LANGUAGE_ASSEMBLY__)
-/* zero page used for uninitialized stuff */
-extern unsigned long empty_zero_page[1024];
-
/*
* BAD_PAGETABLE is used when we need a bogus page-table, while
* BAD_PAGE is used for a bogus page.
@@ -217,10 +157,12 @@ extern unsigned long empty_zero_page[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 ((unsigned long)empty_zero_page)
@@ -234,78 +176,78 @@ extern unsigned long __zero_page(void);
/*
* sizeof(void*) == (1 << SIZEOF_PTR_LOG2)
*/
-#ifdef 0 /* __mips64 */
-#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);
+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) \
- load_pgd((tsk)->tss.pg_dir); \
-} while (0)
+#define SET_PAGE_DIR(tsk,pgdir) (tsk)->tss.pg_dir = ((unsigned long) (pgdir))
extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
/*
- * Convert a page address to a page table pointer and vice versa.
- * Due to the wiered virtual caches in the r-series we might run into
- * problems with cache aliasing. We solve this problem by accessing
- * the pagetables uncached.
- */
-#define page_to_ptp(x) ((__typeof__(x))(((unsigned long) (x)) + (PT_OFFSET - PAGE_OFFSET)))
-#define ptp_to_page(x) ((__typeof__(x))(((unsigned long) (x)) - (PT_OFFSET - PAGE_OFFSET)))
-
-/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
extern inline unsigned long pte_page(pte_t pte)
-{ return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK); }
+{
+ return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK);
+}
extern inline unsigned long pmd_page(pmd_t pmd)
-{ return PAGE_OFFSET + (pmd_val(pmd) & PAGE_MASK); }
+{
+ return pmd_val(pmd);
+}
extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
-{ pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); }
+{
+ pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
+}
-extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
-extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
+extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
-/*
- * Certain architectures need to do special things when pte's
+/* 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;
+ *ptep = pteval;
}
extern inline void pte_clear(pte_t *ptep)
{
- pte_t pte;
-
- pte_val(pte) = 0;
- set_pte(ptep, pte);
+ 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_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE; }
-extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_PRESENT; }
-extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET) | _PAGE_TABLE; }
+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_page(pmd) > (unsigned long) high_memory) ||
+ (pmd_page(pmd) < PAGE_OFFSET));
+}
+
+extern inline int pmd_present(pmd_t pmd)
+{
+ return pmd_val(pmd);
+}
+
+extern inline void pmd_clear(pmd_t *pmdp)
+{
+ pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
+}
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
@@ -315,33 +257,41 @@ extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = ((unsigned long) i
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 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_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_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;
@@ -349,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;
@@ -356,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;
@@ -370,13 +315,14 @@ 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;
@@ -387,30 +333,36 @@ extern inline pte_t pte_mkyoung(pte_t pte)
* 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)
-{ pte_t pte; pte_val(pte) = physpage | pgprot_val(pgprot); return pte; }
+{
+ 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 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 *) (page_to_ptp(pmd_page(*dir))) +
+ return (pte_t *) (pmd_page(*dir)) +
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
}
@@ -419,121 +371,93 @@ extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
* used to allocate a kernel page table - this turns on ASN bits
* 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;
-
- if(!page)
- return;
- /*
- * Flush complete cache - we don't know the virtual address.
- */
- cacheflush(0, ~0, CF_DCACHE|CF_VIRTUAL);
- free_page(ptp_to_page(page));
+ free_page((unsigned long) pte);
}
-extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+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) {
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
- sync_mem();
- page = page_to_ptp(page);
- 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));
pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
return NULL;
}
- return (pte_t *) page_to_ptp(pmd_page(*pmd)) + 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;
- /*
- * Flush complete cache - we don't know the virtual address.
- */
- cacheflush(0, ~0UL, CF_DCACHE|CF_VIRTUAL);
- free_page(ptp_to_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) {
- cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL);
- sync_mem();
- page = page_to_ptp(page);
- 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));
pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
return NULL;
}
- return (pte_t *) page_to_ptp(pmd_page(*pmd)) + 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;
- /*
- * Flush complete cache - we don't know the virtual address.
- */
- cacheflush(0, ~0UL, CF_DCACHE|CF_VIRTUAL);
- free_page(ptp_to_page(page));
+ free_page((unsigned long) pgd);
}
/*
@@ -541,48 +465,313 @@ extern inline void pgd_free(pgd_t * pgd)
*/
extern void (*pgd_init)(unsigned long page);
-extern inline pgd_t * pgd_alloc(void)
+extern inline pgd_t *pgd_alloc(void)
{
unsigned long page;
if(!(page = __get_free_page(GFP_KERNEL)))
return NULL;
+
pgd_init(page);
- return (pgd_t *) page_to_ptp(page);
+ return (pgd_t *) page;
}
extern pgd_t swapper_pg_dir[1024];
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
+extern void (*update_mmu_cache)(struct vm_area_struct *vma,
+ unsigned long address, pte_t pte);
+
+/*
+ * Kernel with 32 bit address space
+ */
+#define SWP_TYPE(entry) (((entry) >> 8) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 15)
+#define SWP_ENTRY(type,offset) (((type) << 8) | ((offset) << 15))
+
+/* TLB operations. */
+extern inline void tlb_probe(void)
{
- tlbflush_page(address);
- /*
- * FIXME: We should also reload a new entry into the TLB to
- * avoid unnecessary exceptions.
- */
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbp\n\t"
+ ".set reorder");
}
-#if 0 /* defined(__mips64) */
+extern inline void tlb_read(void)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbr\n\t"
+ ".set reorder");
+}
-/*
- * For true 64 bit kernel
- */
-#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_write_indexed(void)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwi\n\t"
+ ".set reorder");
+}
-#else
+extern inline void tlb_write_random(void)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ "tlbwr\n\t"
+ ".set reorder");
+}
-/*
- * Kernel with 32 bit address space
- */
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+/* 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;
+}
-#endif
+extern inline void set_entryhi(unsigned long val)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $10\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : : "r" (val));
+}
+
+/* CP0_INDEX register */
+extern inline unsigned long get_index(void)
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mfc0 %0, $0\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : "=r" (val));
+ return val;
+}
+
+extern inline void set_index(unsigned long val)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $0\n\t"
+ ".set mips2\n\t"
+ ".set reorder\n\t"
+ : : "r" (val));
+}
+
+/* CP0_WIRED register */
+extern inline unsigned long get_wired(void)
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mfc0 %0, $6\n\t"
+ ".set mips2\n\t"
+ ".set reorder\n\t"
+ : "=r" (val));
+ return val;
+}
+
+extern inline void set_wired(unsigned long val)
+{
+ __asm__ __volatile__(
+ "\n\t.set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $6\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : : "r" (val));
+}
+
+/* CP0_TAGLO and CP0_TAGHI registers */
+extern inline unsigned long get_taglo(void)
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mfc0 %0, $28\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : "=r" (val));
+ return val;
+}
+
+extern inline void set_taglo(unsigned long val)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $28\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : : "r" (val));
+}
+
+extern inline unsigned long get_taghi(void)
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mfc0 %0, $29\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : "=r" (val));
+ return val;
+}
+
+extern inline void set_taghi(unsigned long val)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $29\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : : "r" (val));
+}
+
+/* CP0_CONTEXT register */
+extern inline unsigned long get_context(void)
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mfc0 %0, $4\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : "=r" (val));
+
+ return val;
+}
+
+extern inline void set_context(unsigned long val)
+{
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "mtc0 %0, $4\n\t"
+ ".set mips2\n\t"
+ ".set reorder"
+ : : "r" (val));
+}
+
+/* Kernel stack allocation/freeing. */
+extern inline unsigned long alloc_kernel_stack(void)
+{
+ unsigned long stack;
+ stack = __get_free_pages(GFP_KERNEL, 1, 0);
+ memset((void *)stack, 0, (size_t) KERNEL_STACK_SIZE);
+
+ return stack;
+}
+
+extern inline void free_kernel_stack(unsigned long stack)
+{
+ free_pages(stack, 1);
+}
#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
diff --git a/include/asm-mips/pica.h b/include/asm-mips/pica.h
new file mode 100644
index 000000000..a1056f845
--- /dev/null
+++ b/include/asm-mips/pica.h
@@ -0,0 +1,181 @@
+/*
+ * Hardware info about Acer PICA 61 and similar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Andreas Busse and Ralf Baechle
+ */
+#ifndef __ASM_MIPS_PICA_H
+#define __ASM_MIPS_PICA_H
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb. The Mips
+ * Magnum R3000 and R4000 machines are similar in many aspects,
+ * but many hardware register are accessible at 0xb9000000 in
+ * instead of 0xe0000000.
+ */
+
+/*
+ * Revision numbers in PICA_ASIC_REVISION
+ *
+ * 0xf0000000 - Rev1
+ * 0xf0000001 - Rev2
+ * 0xf0000002 - Rev3
+ */
+#define PICA_ASIC_REVISION 0xe0000008
+
+/*
+ * The segments of the seven segment LED are mapped
+ * to the control bits as follows:
+ *
+ * (7)
+ * ---------
+ * | |
+ * (2) | | (6)
+ * | (1) |
+ * ---------
+ * | |
+ * (3) | | (5)
+ * | (4) |
+ * --------- . (0)
+ */
+#define PICA_LED 0xe000f000
+
+/*
+ * Some characters for the LED control registers
+ * The original Mips machines seem to have a LED display
+ * with integrated decoder while the Acer machines can
+ * control each of the seven segments and the dot independently.
+ * It only a toy, anyway...
+ */
+#define LED_DOT 0x01
+#define LED_SPACE 0x00
+#define LED_0 0xfc
+#define LED_1 0x60
+#define LED_2 0xda
+#define LED_3 0xf2
+#define LED_4 0x66
+#define LED_5 0xb6
+#define LED_6 0xbe
+#define LED_7 0xe0
+#define LED_8 0xfe
+#define LED_9 0xf6
+#define LED_A 0xee
+#define LED_b 0x3e
+#define LED_C 0x9c
+#define LED_d 0x7a
+#define LED_E 0x9e
+#define LED_F 0x8e
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pica_set_led(unsigned int bits)
+{
+ volatile unsigned int *led_register = (unsigned int *) PICA_LED;
+
+ *led_register = bits;
+}
+
+#endif
+
+/*
+ * i8042 keyboard controller for PICA chipset.
+ * This address is just a guess and seems to differ
+ * from the other mips machines...
+ */
+#define PICA_KEYBOARD_ADDRESS 0xe0005000
+#define PICA_KEYBOARD_DATA 0xe0005000
+#define PICA_KEYBOARD_COMMAND 0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+ unsigned char data;
+ unsigned char command;
+} pica_keyboard_hardware;
+
+typedef struct {
+ unsigned char pad0[3];
+ unsigned char data;
+ unsigned char pad1[3];
+ unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now
+ */
+#define keyboard_hardware pica_keyboard_hardware
+
+#endif
+
+/*
+ * i8042 keyboard controller for most other Mips machines.
+ */
+#define MIPS_KEYBOARD_ADDRESS 0xb9005000
+#define MIPS_KEYBOARD_DATA 0xb9005003
+#define MIPS_KEYBOARD_COMMAND 0xb9005007
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#endif
+
+/*
+ * PICA timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define PICA_TIMER_INTERVAL 0xe0000228
+#define PICA_TIMER_REGISTER 0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+ unsigned int bank2 : 3;
+ unsigned int bank1 : 3;
+ unsigned int mem_bus_width : 1;
+ unsigned int reserved2 : 1;
+ unsigned int page_mode : 1;
+ unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+ unsigned int reserved1 : 23;
+ unsigned int page_mode : 1;
+ unsigned int reserved2 : 1;
+ unsigned int mem_bus_width : 1;
+ unsigned int bank1 : 3;
+ unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PICA_DRAM_CONFIG 0xe00fffe0
+
+/*
+ * PICA interrupt control registers
+ */
+#define PICA_IO_IRQ_SOURCE 0xe0100000
+#define PICA_IO_IRQ_ENABLE 0xe0100002
+
+/*
+ * Pica interrupt enable bits
+ */
+#define PIE_PARALLEL (1<<0)
+#define PIE_FLOPPY (1<<1)
+#define PIE_SOUND (1<<2)
+#define PIE_VIDEO (1<<3)
+#define PIE_ETHERNET (1<<4)
+#define PIE_SCSI (1<<5)
+#define PIE_KEYBOARD (1<<6)
+#define PIE_MOUSE (1<<7)
+#define PIE_SERIAL1 (1<<8)
+#define PIE_SERIAL2 (1<<9)
+
+#endif /* __ASM_MIPS_PICA_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index be6d26a61..1d308a439 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -1,16 +1,15 @@
/*
* include/asm-mips/processor.h
*
- * Copyright (C) 1994, 1995 by Waldorf Electronics
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * 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
-#include <asm/sgidefs.h>
-
#if !defined (__LANGUAGE_ASSEMBLY__)
+#include <asm/cachectl.h>
#include <asm/mipsregs.h>
#include <asm/reg.h>
#include <asm/system.h>
@@ -25,18 +24,25 @@ extern unsigned long event;
/*
* Bus types (default is ISA, but people can check others with these..)
- * There are no Microchannel MIPS machines.
+ * MCA_bus hardcoded to 0 for now.
*
* This needs to be extended since MIPS systems are being delivered with
* numerous different types of bus systems.
*/
extern int EISA_bus;
#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/*
+ * MIPS has no problems with write protection
+ */
+#define wp_works_ok 1
+#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
/*
* User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing. TASK_SIZE
- * for a 64 bit kernel is expandable to 8192PB, of which the current MIPS
+ * 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)
@@ -58,7 +64,7 @@ struct mips_fpu_hard_struct {
*/
struct mips_fpu_soft_struct {
long dummy;
- };
+};
union mips_fpu_union {
struct mips_fpu_hard_struct hard;
@@ -73,63 +79,33 @@ union mips_fpu_union {
* If you change thread_struct remember to change the #defines below too!
*/
struct thread_struct {
- /*
- * saved main processor registers
- */
- __register_t reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
- __register_t reg28, reg29, reg30, reg31;
- /*
- * saved cp0 stuff
- */
- unsigned int cp0_status;
- /*
- * saved fpu/fpu emulator stuff
- */
- union mips_fpu_union fpu;
- /*
- * Other stuff associated with the thread
- */
- long cp0_badvaddr;
+ /* 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 __attribute__ ((aligned (8)));
+
+ /* Other stuff associated with the thread. */
+ unsigned long cp0_badvaddr;
unsigned long error_code;
unsigned long trap_no;
- long ksp; /* Top of kernel stack */
- long pg_dir; /* L1 page table pointer */
+ 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;
- unsigned long segment;
+ 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+SZREG)
-#define TOFF_REG18 (TOFF_REG17+SZREG)
-#define TOFF_REG19 (TOFF_REG18+SZREG)
-#define TOFF_REG20 (TOFF_REG19+SZREG)
-#define TOFF_REG21 (TOFF_REG20+SZREG)
-#define TOFF_REG22 (TOFF_REG21+SZREG)
-#define TOFF_REG23 (TOFF_REG22+SZREG)
-#define TOFF_REG28 (TOFF_REG23+SZREG)
-#define TOFF_REG29 (TOFF_REG28+SZREG)
-#define TOFF_REG30 (TOFF_REG29+SZREG)
-#define TOFF_REG31 (TOFF_REG30+SZREG)
-#define TOFF_CP0_STATUS (TOFF_REG31+SZREG)
-/*
- * Pad for 8 byte boundary!
- */
-#define TOFF_FPU (((TOFF_CP0_STATUS+SZREG)+(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)
-#define TOFF_EX (TOFF_PG_MFLAGS+4)
-
#define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
VM_READ | VM_WRITE | VM_EXEC }
@@ -151,46 +127,39 @@ struct thread_struct {
* Other stuff associated with the process \
*/ \
0, 0, 0, sizeof(init_kernel_stack) + (unsigned long)init_kernel_stack - 8, \
- (unsigned long) swapper_pg_dir - PT_OFFSET, \
+ (unsigned long) swapper_pg_dir, \
/* \
* For now the default is to fix address errors \
*/ \
- MF_FIXADE, \
- KERNEL_DS \
+ MF_FIXADE, 0, 0, 0 \
}
-/*
- * Paul, please check if 4kb stack are sufficient for the R3000. With 4kb
- * I never had a stack overflows on 32 bit R4000 kernels but the almost
- * completly 64bit R4000 kernels from 1.3.63 on need more stack even in
- * trivial situations.
- */
+#ifdef __KERNEL__
+
#define KERNEL_STACK_SIZE 8192
#if !defined (__LANGUAGE_ASSEMBLY__)
-extern unsigned long alloc_kernel_stack(void);
-extern void free_kernel_stack(unsigned long stack);
-
/*
* Return saved PC of a blocked thread.
*/
-extern unsigned long (*thread_saved_pc)(struct thread_struct *t);
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return ((struct pt_regs *)(long)t->reg29)->cp0_epc;
+}
/*
* Do necessary setup to start up a newly executed thread.
*/
extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
/*
* Does the process account for user or for system time?
*/
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x4))
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x18))
-#endif
+
+#endif /* __KERNEL__ */
/*
* Return_address is a replacement for __builtin_return_address(count)
@@ -215,6 +184,5 @@ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long
*/
#define return_address() NULL
#endif
-#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
#endif /* __ASM_MIPS_PROCESSOR_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index ade150d90..ebe4cf888 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -13,89 +13,52 @@
#ifndef __ASM_MIPS_PTRACE_H
#define __ASM_MIPS_PTRACE_H
-#include <asm/sgidefs.h>
-#include <asm/register.h>
-
-/*
- * General purpose registers.
- */
-#define GPR_BASE 0
-#define NGP_REGS 32
-
-/*
- * Floating point registers.
- */
-#define FPR_BASE (GPR_BASE + NGP_REGS)
-#define NFP_REGS 32
-
-/*
- * Signal handlers
- */
-#define SIG_BASE (FPR_BASE + NFP_REGS)
-#define NSIG_HNDLRS 32
-
-/*
- * Special registers.
- */
-#define SPEC_BASE (SIG_BASE + NSIG_HNDLRS)
-#define NSPEC_REGS 7
-#define PC SPEC_BASE
-#define CAUSE (PC + 1)
-#define BADVADDR (CAUSE + 1)
-#define MMHI (BADVADDR + 1)
-#define MMLO (MMHI + 1)
-#define FPC_CSR (MMLO + 1)
-#define FPC_EIR (FPC_CSR + 1)
-#define NPTRC_REGS (FPC_EIR + 1)
+#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 zero/k0/k1 aren't being saved.
+ * 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
- */
- __register_t pad0[6]; /* extra word for alignment */
+ /* Pad bytes for argument save space on the stack. */
+ unsigned long pad0[6];
- /*
- * Saved main processor registers
- */
- __register_t regs[32];
+ /* Saved main processor registers. */
+ unsigned long regs[32];
- /*
- * Other saved registers
- */
- __register_t lo;
- __register_t hi;
- __register_t orig_reg2;
- __register_t orig_reg7;
+ /* Other saved registers. */
+ unsigned long lo;
+ unsigned long hi;
+ unsigned long orig_reg2;
+ unsigned long orig_reg7;
/*
* saved cp0 registers
*/
- __register_t cp0_epc;
- __register_t cp0_badvaddr;
- unsigned int cp0_status;
- unsigned int cp0_cause;
+ unsigned long cp0_epc;
+ unsigned long cp0_badvaddr;
+ unsigned long cp0_status;
+ unsigned long cp0_cause;
};
+#endif /* !(__ASSEMBLY__) */
+
+#include <asm/offset.h>
+
#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
/*
* Does the process account for user or for system time?
*/
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-#define user_mode(regs) (!((regs)->cp0_status & 0x8))
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
#define user_mode(regs) ((regs)->cp0_status & 0x10)
-#endif
#define instruction_pointer(regs) ((regs)->cp0_epc)
-extern void show_regs(struct pt_regs *);
+
+extern void (*show_regs)(struct pt_regs *);
+#endif /* !(__ASSEMBLY__) */
+
#endif
#endif /* __ASM_MIPS_PTRACE_H */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
new file mode 100644
index 000000000..07b0ceff2
--- /dev/null
+++ b/include/asm-mips/r4kcache.h
@@ -0,0 +1,1025 @@
+/* $Id: r4kcache.h,v 1.3 1996/07/22 22:32:59 dm 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/reg.h b/include/asm-mips/reg.h
index 196a1a133..5fd97c23c 100644
--- a/include/asm-mips/reg.h
+++ b/include/asm-mips/reg.h
@@ -1,5 +1,6 @@
/*
- * Makefile for MIPS Linux main source directory
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -15,67 +16,53 @@
* if the order here is changed, it needs to be updated in
* include/asm-mips/stackframe.h
*/
-#define EF_REG1 5
-#define EF_REG2 6
-#define EF_REG3 7
-#define EF_REG4 8
-#define EF_REG5 9
-#define EF_REG6 10
-#define EF_REG7 11
-#define EF_REG8 12
-#define EF_REG9 13
-#define EF_REG10 14
-#define EF_REG11 15
-#define EF_REG12 16
-#define EF_REG13 17
-#define EF_REG14 18
-#define EF_REG15 19
-#define EF_REG16 20
-#define EF_REG17 21
-#define EF_REG18 22
-#define EF_REG19 23
-#define EF_REG20 24
-#define EF_REG21 25
-#define EF_REG22 26
-#define EF_REG23 27
-#define EF_REG24 28
-#define EF_REG25 29
+#define EF_REG0 6
+#define EF_REG1 7
+#define EF_REG2 8
+#define EF_REG3 9
+#define EF_REG4 10
+#define EF_REG5 11
+#define EF_REG6 12
+#define EF_REG7 13
+#define EF_REG8 14
+#define EF_REG9 15
+#define EF_REG10 16
+#define EF_REG11 17
+#define EF_REG12 18
+#define EF_REG13 19
+#define EF_REG14 20
+#define EF_REG15 21
+#define EF_REG16 22
+#define EF_REG17 23
+#define EF_REG18 24
+#define EF_REG19 25
+#define EF_REG20 26
+#define EF_REG21 27
+#define EF_REG22 28
+#define EF_REG23 29
+#define EF_REG24 30
+#define EF_REG25 31
/*
* k0/k1 unsaved
*/
-#define EF_REG28 30
-#define EF_REG29 31
-#define EF_REG30 32
-#define EF_REG31 33
+#define EF_REG28 34
+#define EF_REG29 35
+#define EF_REG30 36
+#define EF_REG31 37
/*
* Saved special registers
*/
-#define EF_LO 34
-#define EF_HI 35
-#define EF_ORIG_REG2 36
+#define EF_LO 38
+#define EF_HI 39
+#define EF_ORIG_REG2 40
+#define EF_ORIG_REG7 41
-#if 0
-/*
- * saved cp0 registers
- */
-#define EF_CP0_EPC 37
-#define EF_CP0_STATUS 36
-#define EF_CP0_CAUSE 38
-#endif
-
-#ifdef __mips64
-#define EF_SIZE 304
-#else
-#define EF_SIZE 160
-#endif
+#define EF_CP0_EPC 42
+#define EF_CP0_BADVADDR 43
+#define EF_CP0_STATUS 44
+#define EF_CP0_CAUSE 45
-#if 0
-/*
- * Map register number into core file offset.
- */
-#define CORE_REG(reg, ubase) \
- (((unsigned long *)((unsigned long)(ubase)))[reg])
-#endif
+#define EF_SIZE 180
#endif /* __ASM_MIPS_REG_H */
diff --git a/include/asm-mips/register.h b/include/asm-mips/register.h
deleted file mode 100644
index 9a19187e0..000000000
--- a/include/asm-mips/register.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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_REGISTER_H
-#define __ASM_MIPS_REGISTER_H
-
-/*
- * Types to represent a register
- */
-#ifdef __mips64
-/*
- * The R4000 port makes use of the 64 bit wide registers
- */
-#ifndef __LANGUAGE_ASSEMBLY__
-typedef long long __register_t;
-typedef unsigned long long __uregister_t;
-#endif
-
-#else
-
-/*
- * Good 'ole R3000 has only 32 bit wide registers
- */
-#ifndef __LANGUAGE_ASSEMBLY__
-typedef long __register_t;
-typedef unsigned long __uregister_t;
-#endif
-#endif
-
-#endif /* __ASM_MIPS_REGISTER_H */
diff --git a/include/asm-mips/segment.h b/include/asm-mips/segment.h
index c6a684e8d..0453d97da 100644
--- a/include/asm-mips/segment.h
+++ b/include/asm-mips/segment.h
@@ -1,6 +1,6 @@
-#ifndef __MIPS_SEGMENT_H
-#define __MIPS_SEGMENT_H
+#ifndef __ALPHA_SEGMENT_H
+#define __ALPHA_SEGMENT_H
/* Only here because we have some old header files that expect it.. */
-#endif /* __MIPS_SEGMENT_H */
+#endif
diff --git a/include/asm-mips/sgi.h b/include/asm-mips/sgi.h
new file mode 100644
index 000000000..b49623eaf
--- /dev/null
+++ b/include/asm-mips/sgi.h
@@ -0,0 +1,42 @@
+/* $Id: sgi.h,v 1.3 1996/06/25 07:18:24 dm 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
index 000000000..45ac539d4
--- /dev/null
+++ b/include/asm-mips/sgialib.h
@@ -0,0 +1,118 @@
+/* $Id: sgialib.h,v 1.7 1996/06/08 06:05:15 dm 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
index 000000000..2e820feca
--- /dev/null
+++ b/include/asm-mips/sgiarcs.h
@@ -0,0 +1,351 @@
+/* $Id: sgiarcs.h,v 1.4 1996/06/08 04:48:43 dm 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/sgihpc.h b/include/asm-mips/sgihpc.h
new file mode 100644
index 000000000..e3c28b495
--- /dev/null
+++ b/include/asm-mips/sgihpc.h
@@ -0,0 +1,340 @@
+/* $Id: sgihpc.h,v 1.7 1996/06/16 07:22:30 dm 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
index 000000000..70bec8b1e
--- /dev/null
+++ b/include/asm-mips/sgimc.h
@@ -0,0 +1,223 @@
+/* $Id: sgimc.h,v 1.4 1996/06/25 07:18:24 dm 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
index 000000000..31319f829
--- /dev/null
+++ b/include/asm-mips/sgint23.h
@@ -0,0 +1,179 @@
+/* $Id: sgint23.h,v 1.5 1996/06/12 00:44:01 dm Exp $
+ * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _MIPS_SGINT23_H
+#define _MIPS_SGINT23_H
+
+/* These are the virtual IRQ numbers, we divide all IRQ's into
+ * 'spaces', the 'space' determines where and how to enable/disable
+ * that particular IRQ on an SGI machine. Add new 'spaces' as new
+ * IRQ hardware is supported.
+ */
+#define SGINT_LOCAL0 0 /* INDY has 8 local0 irq levels */
+#define SGINT_LOCAL1 8 /* INDY has 8 local1 irq levels */
+#define SGINT_LOCAL2 16 /* INDY has 8 local2 vectored irq levels */
+#define SGINT_LOCAL3 24 /* INDY has 8 local3 vectored irq levels */
+#define SGINT_GIO 32 /* INDY has 9 GIO irq levels */
+#define SGINT_HPCDMA 41 /* INDY has 11 HPCDMA irq _sources_ */
+#define SGINT_END 52 /* End of 'spaces' */
+
+/* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */
+#define SGI_INT2_BASE 0x1fb80100 /* physical */
+#define SGI_INT3_BASE 0x1fbd9880 /* physical */
+
+struct sgi_ioc_ints {
+#ifdef __MIPSEB__
+ unsigned char _unused0[3];
+ volatile unsigned char istat0; /* Interrupt status zero */
+#else
+ volatile unsigned char istat0; /* Interrupt status zero */
+ unsigned char _unused0[3];
+#endif
+#define ISTAT0_FFULL 0x01
+#define ISTAT0_SCSI0 0x02
+#define ISTAT0_SCSI1 0x04
+#define ISTAT0_ENET 0x08
+#define ISTAT0_GFXDMA 0x10
+#define ISTAT0_LPR 0x20
+#define ISTAT0_HPC2 0x40
+#define ISTAT0_LIO2 0x80
+
+#ifdef __MIPSEB__
+ unsigned char _unused1[3];
+ volatile unsigned char imask0; /* Interrupt mask zero */
+ unsigned char _unused2[3];
+ volatile unsigned char istat1; /* Interrupt status one */
+#else
+ volatile unsigned char imask0; /* Interrupt mask zero */
+ unsigned char _unused1[3];
+ volatile unsigned char istat1; /* Interrupt status one */
+ unsigned char _unused2[3];
+#endif
+#define ISTAT1_ISDNI 0x01
+#define ISTAT1_PWR 0x02
+#define ISTAT1_ISDNH 0x04
+#define ISTAT1_LIO3 0x08
+#define ISTAT1_HPC3 0x10
+#define ISTAT1_AFAIL 0x20
+#define ISTAT1_VIDEO 0x40
+#define ISTAT1_GIO2 0x80
+
+#ifdef __MIPSEB__
+ unsigned char _unused3[3];
+ volatile unsigned char imask1; /* Interrupt mask one */
+ unsigned char _unused4[3];
+ volatile unsigned char vmeistat; /* VME interrupt status */
+ unsigned char _unused5[3];
+ volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+ unsigned char _unused6[3];
+ volatile unsigned char cmeimask1; /* VME interrupt mask one */
+ unsigned char _unused7[3];
+ volatile unsigned char cmepol; /* VME polarity */
+#else
+ volatile unsigned char imask1; /* Interrupt mask one */
+ unsigned char _unused3[3];
+ volatile unsigned char vmeistat; /* VME interrupt status */
+ unsigned char _unused4[3];
+ volatile unsigned char cmeimask0; /* VME interrupt mask zero */
+ unsigned char _unused5[3];
+ volatile unsigned char cmeimask1; /* VME interrupt mask one */
+ unsigned char _unused6[3];
+ volatile unsigned char cmepol; /* VME polarity */
+ unsigned char _unused7[3];
+#endif
+};
+
+struct sgi_ioc_timers {
+#ifdef __MIPSEB__
+ unsigned char _unused0[3];
+ volatile unsigned char tcnt0; /* counter 0 */
+ unsigned char _unused1[3];
+ volatile unsigned char tcnt1; /* counter 1 */
+ unsigned char _unused2[3];
+ volatile unsigned char tcnt2; /* counter 2 */
+ unsigned char _unused3[3];
+ volatile unsigned char tcword; /* control word */
+#else
+ volatile unsigned char tcnt0; /* counter 0 */
+ unsigned char _unused0[3];
+ volatile unsigned char tcnt1; /* counter 1 */
+ unsigned char _unused1[3];
+ volatile unsigned char tcnt2; /* counter 2 */
+ unsigned char _unused2[3];
+ volatile unsigned char tcword; /* control word */
+ unsigned char _unused3[3];
+#endif
+};
+
+/* Timer control word bits. */
+#define SGINT_TCWORD_BCD 0x01 /* Use BCD mode for counters */
+#define SGINT_TCWORD_MMASK 0x0e /* Mode bitmask. */
+#define SGINT_TCWORD_MITC 0x00 /* IRQ on terminal count (doesn't work) */
+#define SGINT_TCWORD_MOS 0x02 /* One-shot IRQ mode. */
+#define SGINT_TCWORD_MRGEN 0x04 /* Normal rate generation */
+#define SGINT_TCWORD_MSWGEN 0x06 /* Square wave generator mode */
+#define SGINT_TCWORD_MSWST 0x08 /* Software strobe */
+#define SGINT_TCWORD_MHWST 0x0a /* Hardware strobe */
+#define SGINT_TCWORD_CMASK 0x30 /* Command mask */
+#define SGINT_TCWORD_CLAT 0x00 /* Latch command */
+#define SGINT_TCWORD_CLSB 0x10 /* LSB read/write */
+#define SGINT_TCWORD_CMSB 0x20 /* MSB read/write */
+#define SGINT_TCWORD_CALL 0x30 /* Full counter read/write */
+#define SGINT_TCWORD_CNT0 0x00 /* Select counter zero */
+#define SGINT_TCWORD_CNT1 0x40 /* Select counter one */
+#define SGINT_TCWORD_CNT2 0x80 /* Select counter two */
+#define SGINT_TCWORD_CRBCK 0xc0 /* Readback command */
+
+#define SGINT_TCSAMP_COUNTER 0x164
+
+struct sgi_int2_regs {
+ struct sgi_ioc_ints ints;
+
+ volatile unsigned long ledbits; /* LED control bits */
+#define INT2_LED_TXCLK 0x01 /* GPI to TXCLK enable */
+#define INT2_LED_SERSLCT0 0x02 /* serial port0: 0=apple 1=pc */
+#define INT2_LED_SERSLCT1 0x04 /* serial port1: 0=apple 1=pc */
+#define INT2_LED_CHEAPER 0x08 /* 0=cheapernet 1=ethernet */
+#define INT2_LED_POWEROFF 0x10 /* Power-off request, active high */
+
+#ifdef __MIPSEB__
+ unsigned char _unused0[3];
+ volatile unsigned char tclear; /* Timer clear strobe address */
+#else
+ volatile unsigned char tclear; /* Timer clear strobe address */
+ unsigned char _unused0[3];
+#endif
+#define INT2_TCLEAR_T0CLR 0x1 /* Clear timer0 IRQ */
+#define INT2_TCLEAR_T1CLR 0x2 /* Clear timer1 IRQ */
+
+ unsigned long _unused[3];
+ struct sgi_ioc_timers timers;
+};
+
+struct sgi_int3_regs {
+ struct sgi_ioc_ints ints;
+
+#ifdef __MIPSEB__
+ unsigned char _unused0[3];
+ volatile unsigned char tclear; /* Timer clear strobe address */
+#else
+ volatile unsigned char tclear; /* Timer clear strobe address */
+ unsigned char _unused0[3];
+#endif
+ volatile unsigned long estatus; /* Error status reg */
+ unsigned long _unused1[2];
+ struct sgi_ioc_timers timers;
+};
+
+extern struct sgi_int2_regs *sgi_i2regs;
+extern struct sgi_int3_regs *sgi_i3regs;
+extern struct sgi_ioc_ints *ioc_icontrol;
+extern struct sgi_ioc_timers *ioc_timers;
+extern volatile unsigned char *ioc_tclear;
+
+extern void sgint_init(void);
+extern void indy_timer_init(void);
+
+#endif /* !(_MIPS_SGINT23_H) */
diff --git a/include/asm-mips/shmparam.h b/include/asm-mips/shmparam.h
index 9c5a38a40..b2441c81a 100644
--- a/include/asm-mips/shmparam.h
+++ b/include/asm-mips/shmparam.h
@@ -39,7 +39,7 @@
#define SHMALL /* max shm system wide (pages) */ \
(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
/*
- * This constant is very large but the ABI in its wisdom says ...
+ * This constant is very large but the ABI in it's wisdom says ...
*/
#define SHMLBA 0x40000 /* attach addr a multiple of this */
#define SHMSEG SHMMNI /* max shared segs per process */
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index 135d83df6..a1f7613f4 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -18,6 +18,7 @@
#endif
#if defined(__LANGUAGE_C__) || \
+ defined(_LANGUAGE_C) || \
defined(__LANGUAGE_C_PLUS_PLUS__) || \
defined(__LANGUAGE_OBJECTIVE_C__)
diff --git a/include/asm-mips/slots.h b/include/asm-mips/slots.h
deleted file mode 100644
index 387802333..000000000
--- a/include/asm-mips/slots.h
+++ /dev/null
@@ -1,23 +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
-
-#include <linux/config.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.
- */
-#ifdef CONFIG_DESKSTATION_RPC44
-#define SLOTSPACE 0xa0000000
-#else
-#define SLOTSPACE 0xe1000000
-#endif
-
-#endif /* __ASM_MIPS_SLOTS_H */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
new file mode 100644
index 000000000..304506aee
--- /dev/null
+++ b/include/asm-mips/sni.h
@@ -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_SNI_H
+#define __ASM_MIPS_SNI_H
+
+#define SNI_PORT_BASE 0xb4000000
+
+#endif /* __ASM_MIPS_SNI_H */
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 3cdbb61ef..4a110338a 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -1,351 +1,114 @@
/*
- * Makefile for MIPS Linux main source directory
+ * include/asm-mips/stackframe.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 and Paul M. Antoine.
- * Additional R3000 support by Didier Frick <dfrick@dial.eunet.ch>
- * for ACN S.A, Copyright (C) 1996 by ACN S.A
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
*/
#ifndef __ASM_MIPS_STACKFRAME_H
#define __ASM_MIPS_STACKFRAME_H
-#include <asm/sgidefs.h>
#include <asm/asm.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*6 bytes are argument save space for C subroutines.
- * zero doesn't get saved; it's just a placeholder.
- */
-#define FR_REG0 (SZREG*6)
-#define FR_REG1 ((FR_REG0) + SZREG)
-#define FR_REG2 ((FR_REG1) + SZREG)
-#define FR_REG3 ((FR_REG2) + SZREG)
-#define FR_REG4 ((FR_REG3) + SZREG)
-#define FR_REG5 ((FR_REG4) + SZREG)
-#define FR_REG6 ((FR_REG5) + SZREG)
-#define FR_REG7 ((FR_REG6) + SZREG)
-#define FR_REG8 ((FR_REG7) + SZREG)
-#define FR_REG9 ((FR_REG8) + SZREG)
-#define FR_REG10 ((FR_REG9) + SZREG)
-#define FR_REG11 ((FR_REG10) + SZREG)
-#define FR_REG12 ((FR_REG11) + SZREG)
-#define FR_REG13 ((FR_REG12) + SZREG)
-#define FR_REG14 ((FR_REG13) + SZREG)
-#define FR_REG15 ((FR_REG14) + SZREG)
-#define FR_REG16 ((FR_REG15) + SZREG)
-#define FR_REG17 ((FR_REG16) + SZREG)
-#define FR_REG18 ((FR_REG17) + SZREG)
-#define FR_REG19 ((FR_REG18) + SZREG)
-#define FR_REG20 ((FR_REG19) + SZREG)
-#define FR_REG21 ((FR_REG20) + SZREG)
-#define FR_REG22 ((FR_REG21) + SZREG)
-#define FR_REG23 ((FR_REG22) + SZREG)
-#define FR_REG24 ((FR_REG23) + SZREG)
-#define FR_REG25 ((FR_REG24) + SZREG)
-
-/*
- * $26 (k0) and $27 (k1) not saved - just placeholders
- */
-#define FR_REG26 ((FR_REG25) + SZREG)
-#define FR_REG27 ((FR_REG26) + SZREG)
-
-#define FR_REG28 ((FR_REG27) + SZREG)
-#define FR_REG29 ((FR_REG28) + SZREG)
-#define FR_REG30 ((FR_REG29) + SZREG)
-#define FR_REG31 ((FR_REG30) + SZREG)
-
-/*
- * Saved special registers
- */
-#define FR_LO ((FR_REG31) + SZREG)
-#define FR_HI ((FR_LO) + SZREG)
-#define FR_ORIG_REG2 ((FR_HI) + SZREG)
-#define FR_ORIG_REG7 ((FR_ORIG_REG2) + SZREG)
-
-/*
- * Saved cp0 registers follow
- */
-#define FR_EPC ((FR_ORIG_REG7) + SZREG)
-#define FR_BADVADDR ((FR_EPC) + SZREG)
-#define FR_STATUS ((FR_BADVADDR) + SZREG)
-#define FR_CAUSE ((FR_STATUS) + 4)
-
-/*
- * Size of stack frame, word/double word alignment
- */
-#define FR_SIZE (((FR_CAUSE + 4) + ALSZ) & ALMASK)
-
-/*
- * Load the global pointer. Only for ELF executables global pointer
- * optimization is possible, so we only load the global pointer for
- * ELF kernels.
- */
-#if 0
-#define LOAD_GP la gp,_gp
-#else
-#define LOAD_GP
-#endif
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-
-#define SAVE_ALL \
- mfc0 k0,CP0_STATUS; \
- li k1,ST0_CU0; \
- and k0,k1; \
- bnez k0,8f; \
- move k1,sp; \
- nop; \
- /* \
- * Called from user mode, new stack \
- */ \
- lw k1,kernelsp; \
-8: move k0,sp; \
- subu sp,k1,FR_SIZE; \
- sw k0,FR_REG29(sp); \
- sw $3,FR_REG3(sp); \
- mfc0 $3,CP0_STATUS; \
- nop; \
- sw $3,FR_STATUS(sp); \
- li k1,ST0_CU0; \
- or k1,$3; \
- mtc0 k1,CP0_STATUS; \
- nop; \
- mfc0 $3,CP0_ENTRYHI; \
- nop; \
- sw $3,FR_ENTRYHI(sp); \
- mfc0 $3,CP0_CAUSE; \
- nop; \
- sw $3,FR_CAUSE(sp); \
- mfc0 $3,CP0_EPC; \
- nop; \
- sw $3,FR_EPC(sp); \
- mfc0 $3,CP0_BADVADDR; \
- nop; \
- sw $3,FR_BADVADDR(sp); \
- mfhi $3; \
- sw $3,FR_HI(sp); \
- mflo $3; \
- sw $3,FR_LO(sp); \
- sw $1,FR_REG1(sp); \
- sw $2,FR_REG2(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); \
- LOAD_GP
+#include <asm/offset.h>
+
+#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);
/*
* Note that we restore the IE flags from stack. This means
* that a modified IE mask will be nullified.
*/
-/*
- * FIXME: Don't need to clear these bits on R[236]000's??
- *
- mfc0 t0,CP0_STATUS; \
- ori t0,0x1f; \
- xori t0,0x1f; \
- mtc0 t0,CP0_STATUS; \
- */
-#define RESTORE_ALL \
- lw v1,FR_LO(sp); \
- lw v0,FR_HI(sp); \
- mtlo v1; \
- 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 k1,FR_STATUS(sp); \
- lw sp,FR_REG29(sp); \
- ori k1,3; \
- xori k1,3; \
- mtc0 k1,CP0_STATUS; \
- nop
-
-/*
- * We disable interrupts when restoring the status register because:
- * 1) the ret_from_syscall routine uses k0/k1 to preserve values around
- * the RESTORE_ALL
- * 2) the rfe instruction will restore the IE and KU flags to their
- * previous value.
- */
-
-#define CLI \
- mfc0 t1,$12; \
- li t0,ST0_CU0|1; \
- or t1,t1,t0; \
- xori t1,1; \
- mtc0 t1,$12; \
- nop; \
- nop
-
-#define STI \
- mfc0 t1,$12; \
- li t0,ST0_CU0|1; \
- or t1,t1,t0; \
- mtc0 t1,$12; \
- nop; \
- nop
-
-#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
-
-#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 \
- */ \
- lw k1,kernelsp; \
-8: move k0,sp; \
- subu sp,k1,FR_SIZE; \
- sd k0,FR_REG29(sp); \
- sd $3,FR_REG3(sp); \
- mfc0 $3,CP0_STATUS; \
- sw $3,FR_STATUS(sp); \
- mfc0 $3,CP0_CAUSE; \
- sw $3,FR_CAUSE(sp); \
- dmfc0 $3,CP0_EPC; \
- sd $3,FR_EPC(sp); \
- mfhi $3; \
- sd $3,FR_HI(sp); \
- mflo $3; \
- sd $3,FR_LO(sp); \
- sd $1,FR_REG1(sp); \
- sd $2,FR_REG2(sp); \
- sd $4,FR_REG4(sp); \
- sd $5,FR_REG5(sp); \
- sd $6,FR_REG6(sp); \
- sd $7,FR_REG7(sp); \
- sd $8,FR_REG8(sp); \
- sd $9,FR_REG9(sp); \
- sd $10,FR_REG10(sp); \
- sd $11,FR_REG11(sp); \
- sd $12,FR_REG12(sp); \
- sd $13,FR_REG13(sp); \
- sd $14,FR_REG14(sp); \
- sd $15,FR_REG15(sp); \
- sd $16,FR_REG16(sp); \
- sd $17,FR_REG17(sp); \
- sd $18,FR_REG18(sp); \
- sd $19,FR_REG19(sp); \
- sd $20,FR_REG20(sp); \
- sd $21,FR_REG21(sp); \
- sd $22,FR_REG22(sp); \
- sd $23,FR_REG23(sp); \
- sd $24,FR_REG24(sp); \
- sd $25,FR_REG25(sp); \
- sd $28,FR_REG28(sp); \
- sd $30,FR_REG30(sp); \
- sd $31,FR_REG31(sp); \
- LOAD_GP
-
-/*
- * Note that we restore the IE flags from stack. This means
- * that a modified IE mask will be nullified.
- */
-#define RESTORE_ALL \
- mfc0 t0,CP0_STATUS; \
- ori t0,0x1f; \
- xori t0,0x1f; \
- mtc0 t0,CP0_STATUS; \
- \
- lw v0,FR_STATUS(sp); \
- ld v1,FR_LO(sp); \
- mtc0 v0,CP0_STATUS; \
- mtlo v1; \
- ld v0,FR_HI(sp); \
- ld v1,FR_EPC(sp); \
- mthi v0; \
- dmtc0 v1,CP0_EPC; \
- ld $31,FR_REG31(sp); \
- ld $30,FR_REG30(sp); \
- ld $28,FR_REG28(sp); \
- ld $25,FR_REG25(sp); \
- ld $24,FR_REG24(sp); \
- ld $23,FR_REG23(sp); \
- ld $22,FR_REG22(sp); \
- ld $21,FR_REG21(sp); \
- ld $20,FR_REG20(sp); \
- ld $19,FR_REG19(sp); \
- ld $18,FR_REG18(sp); \
- ld $17,FR_REG17(sp); \
- ld $16,FR_REG16(sp); \
- ld $15,FR_REG15(sp); \
- ld $14,FR_REG14(sp); \
- ld $13,FR_REG13(sp); \
- ld $12,FR_REG12(sp); \
- ld $11,FR_REG11(sp); \
- ld $10,FR_REG10(sp); \
- ld $9,FR_REG9(sp); \
- ld $8,FR_REG8(sp); \
- ld $7,FR_REG7(sp); \
- ld $6,FR_REG6(sp); \
- ld $5,FR_REG5(sp); \
- ld $4,FR_REG4(sp); \
- ld $3,FR_REG3(sp); \
- ld $2,FR_REG2(sp); \
- ld $1,FR_REG1(sp); \
- ld sp,FR_REG29(sp) /* Deallocate stack */ \
+#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);
/*
* Move to kernel mode and disable interrupts.
@@ -373,6 +136,4 @@
xori t0,0x1e; \
mtc0 t0,CP0_STATUS
-#endif /* _MIPS_ISA >= MIPS3 */
-
#endif /* __ASM_MIPS_STACKFRAME_H */
diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h
index 1773abd81..2fb241775 100644
--- a/include/asm-mips/string.h
+++ b/include/asm-mips/string.h
@@ -10,11 +10,6 @@
#ifndef __ASM_MIPS_STRING_H
#define __ASM_MIPS_STRING_H
-#ifdef __KERNEL__
-
-#include <linux/linkage.h>
-#include <asm/sgidefs.h>
-
#define __HAVE_ARCH_STRCPY
extern __inline__ char *strcpy(char *__dest, __const__ char *__src)
{
@@ -122,318 +117,16 @@ extern __inline__ int strncmp(__const__ char *__cs, __const__ char *__ct, size_t
}
#define __HAVE_ARCH_MEMSET
-/*
- * Ok, this definately looks braindead. I tried several other variants
- * some of which GCC wasn't able to optimize or which made GCC consume
- * extreme amounts of memory.
- * This code attempts never to generate address errors which require
- * expensive software emulation. For this purpose GCC's __alignof__
- * seems to be perfect. Unfortunately GCC 2.7.2 complains about
- * __alignof__(*p) when p is a pointer to void. For now I ignore these
- * warnings.
- */
-
-extern void __generic_memset_b(void *__s, int __c, size_t __count);
-extern void __generic_memset_dw(void *__s, unsigned long long __c,
- size_t __count);
-
-/*
- * The constant c handling looks wired but it combines minimal code
- * size with fast execution.
- */
-#define __generic_memset(s, c, count, const_c) \
-({if(const_c) { \
- unsigned long long __dwc; \
-\
- __dwc = c & 0xff; \
- __dwc = (__dwc << 8) | __dwc; \
- __dwc = (__dwc << 16) | __dwc; \
- __dwc = (__dwc << 32) | __dwc; \
- __generic_memset_dw(s, __dwc, count); \
- } \
-else \
- __generic_memset_b(s, c, count); \
-})
-
-extern __inline__ void __const_count_memset1(void *__s, int __c, size_t __count,
- int __const_c)
-{
- switch(__count) {
- case 0: return;
- case 1: *(0+(char *)__s) = __c;
- return;
- case 2: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- return;
- case 3: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- return;
- case 4: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- *(3+(char *)__s) = __c;
- return;
- case 5: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- *(3+(char *)__s) = __c;
- *(4+(char *)__s) = __c;
- return;
- case 6: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- *(3+(char *)__s) = __c;
- *(4+(char *)__s) = __c;
- *(5+(char *)__s) = __c;
- return;
- case 7: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- *(3+(char *)__s) = __c;
- *(4+(char *)__s) = __c;
- *(5+(char *)__s) = __c;
- *(6+(char *)__s) = __c;
- return;
- case 8: *(0+(char *)__s) = __c;
- *(1+(char *)__s) = __c;
- *(2+(char *)__s) = __c;
- *(3+(char *)__s) = __c;
- *(4+(char *)__s) = __c;
- *(5+(char *)__s) = __c;
- *(6+(char *)__s) = __c;
- *(7+(char *)__s) = __c;
- return;
- }
- __generic_memset(__s, __c, __count, __const_c);
- return;
-}
-
-extern __inline__ void __const_count_memset2(void *__s, int __c, size_t __count,
- int __const_c)
-{
- switch(__count) {
- case 0: return;
- case 2: *(0+(short *)__s) = 0x0101 * __c;
- return;
- case 4: *(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- return;
- case 6: *(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- return;
- case 8: *(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- *(3+(short *)__s) = 0x0101 * __c;
- return;
- case 10:*(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- *(3+(short *)__s) = 0x0101 * __c;
- *(4+(short *)__s) = 0x0101 * __c;
- return;
- case 12:*(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- *(3+(short *)__s) = 0x0101 * __c;
- *(4+(short *)__s) = 0x0101 * __c;
- *(5+(short *)__s) = 0x0101 * __c;
- return;
- case 14:*(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- *(3+(short *)__s) = 0x0101 * __c;
- *(4+(short *)__s) = 0x0101 * __c;
- *(5+(short *)__s) = 0x0101 * __c;
- *(6+(short *)__s) = 0x0101 * __c;
- return;
- case 16:*(0+(short *)__s) = 0x0101 * __c;
- *(1+(short *)__s) = 0x0101 * __c;
- *(2+(short *)__s) = 0x0101 * __c;
- *(3+(short *)__s) = 0x0101 * __c;
- *(4+(short *)__s) = 0x0101 * __c;
- *(5+(short *)__s) = 0x0101 * __c;
- *(6+(short *)__s) = 0x0101 * __c;
- *(7+(short *)__s) = 0x0101 * __c;
- return;
- }
- __generic_memset(__s, __c, __count, __const_c);
- return;
-}
-
-extern __inline__ void __const_count_memset4(void *__s, int __c, size_t __count,
- int __const_c)
-{
- switch(__count) {
- case 0: return;
- case 4: *(0+(int *)__s) = 0x01010101 * __c;
- return;
- case 8: *(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- return;
- case 12:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- return;
- case 16:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- *(3+(int *)__s) = 0x01010101 * __c;
- return;
- case 20:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- *(3+(int *)__s) = 0x01010101 * __c;
- *(4+(int *)__s) = 0x01010101 * __c;
- return;
- case 24:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- *(3+(int *)__s) = 0x01010101 * __c;
- *(4+(int *)__s) = 0x01010101 * __c;
- *(5+(int *)__s) = 0x01010101 * __c;
- return;
- case 28:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- *(3+(int *)__s) = 0x01010101 * __c;
- *(4+(int *)__s) = 0x01010101 * __c;
- *(5+(int *)__s) = 0x01010101 * __c;
- *(6+(int *)__s) = 0x01010101 * __c;
- return;
- case 32:*(0+(int *)__s) = 0x01010101 * __c;
- *(1+(int *)__s) = 0x01010101 * __c;
- *(2+(int *)__s) = 0x01010101 * __c;
- *(3+(int *)__s) = 0x01010101 * __c;
- *(4+(int *)__s) = 0x01010101 * __c;
- *(5+(int *)__s) = 0x01010101 * __c;
- *(6+(int *)__s) = 0x01010101 * __c;
- *(7+(int *)__s) = 0x01010101 * __c;
- return;
- }
- __generic_memset(__s, __c, __count, __const_c);
- return;
-}
-
-extern __inline__ void __const_count_memset8(void *__s, int __c, size_t __count,
- int __const_c)
-{
- unsigned long long __dwc;
-
- __dwc = __c & 0xff;
- __dwc = (__dwc << 8) | __dwc;
- __dwc = (__dwc << 16) | __dwc;
- __dwc = (__dwc << 32) | __dwc;
- switch(__count) {
- case 0: return;
- case 8: *(0+(long long *)__s) = __dwc;
- return;
- case 16:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- return;
- case 24:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- return;
- case 32:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- *(3+(long long *)__s) = __dwc;
- return;
- case 40:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- *(3+(long long *)__s) = __dwc;
- *(4+(long long *)__s) = __dwc;
- return;
- case 48:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- *(3+(long long *)__s) = __dwc;
- *(4+(long long *)__s) = __dwc;
- *(5+(long long *)__s) = __dwc;
- return;
- case 56:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- *(3+(long long *)__s) = __dwc;
- *(4+(long long *)__s) = __dwc;
- *(5+(long long *)__s) = __dwc;
- *(6+(long long *)__s) = __dwc;
- return;
- case 64:*(0+(long long *)__s) = __dwc;
- *(1+(long long *)__s) = __dwc;
- *(2+(long long *)__s) = __dwc;
- *(3+(long long *)__s) = __dwc;
- *(4+(long long *)__s) = __dwc;
- *(5+(long long *)__s) = __dwc;
- *(6+(long long *)__s) = __dwc;
- *(7+(long long *)__s) = __dwc;
- return;
- }
- __generic_memset(__s, __c, __count, __const_c);
- return;
-}
-
-extern __inline__ void * __const_count_memset(void *__s, int __c,
- size_t __count, int __align,
- int __const_c)
-{
- switch(__align) {
- /*
- * We only want this for the 64 bit CPUs; this gets
- * too bloated on 32 bit.
- */
- case 1: __const_count_memset1(__s, __c, __count, __const_c);
- return __s;
- case 2: __const_count_memset2(__s, __c, __count, __const_c);
- return __s;
- case 4: __const_count_memset4(__s, __c, __count, __const_c);
- return __s;
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS5)
- case 8: __const_count_memset8(__s, __c, __count, __const_c);
- return __s;
-#endif
- }
- __generic_memset(__s, __c, __count, __const_c);
- return __s;
-}
-
-#define memset(s, c, count) \
-(__builtin_constant_p(count) ? \
- __const_count_memset((s),(c),(count),__alignof__(*(s)), \
- __builtin_constant_p(c)) : \
- __generic_memset((s),(c),(count),__builtin_constant_p(c)))
+extern void *memset(void *__s, char __c, size_t __count);
#define __HAVE_ARCH_MEMCPY
-extern void __memcpy(void *__to, __const__ void *__from, size_t __n);
-extern __inline__ void *memcpy(void *__to, __const__ void *__from, size_t __n)
-{
- __memcpy(__to, __from, __n);
-
- return __to;
-}
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
#define __HAVE_ARCH_MEMMOVE
-extern void __memmove(void *__dest, __const__ void *__src, size_t __n);
-extern __inline__ void *memmove(void *__dest, __const__ void *__src, size_t __n)
-{
- __memmove(__dest, __src, __n);
-
- return __dest;
-}
+extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
#define __HAVE_ARCH_BCOPY
-extern __inline__ char *bcopy(__const__ char *__src, char *__dest, size_t __count)
-{
- __memmove(__dest, __src, __count);
-
- return __dest;
-}
+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)
@@ -442,15 +135,19 @@ extern __inline__ void *memscan(void *__addr, int __c, size_t __size)
if (!__size)
return __addr;
- __asm__(".set\tnoat\n"
+ __asm__(".set\tnoreorder\n\t"
+ ".set\tnoat\n"
"1:\tlbu\t$1,(%0)\n\t"
- ".set\tnoreorder\n\t"
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
+ "nop\n\t"
+#endif
"beq\t$1,%3,2f\n\t"
- "addiu\t%0,1\t\t\t# delay slot\n\t"
- ".set\treorder\n\t"
- ".set\tat\n\t"
+ "addiu\t%0,1\n\t"
"bne\t%0,%2,1b\n\t"
- "2:\n"
+ "nop\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n"
+ "2:"
: "=r" (__addr)
: "0" (__addr), "1" (__end), "r" (__c)
: "$1");
@@ -458,6 +155,4 @@ extern __inline__ void *memscan(void *__addr, int __c, size_t __size)
return __addr;
}
-#endif /* __KERNEL__ */
-
#endif /* __ASM_MIPS_STRING_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 5489dd87a..4bb2bf1c7 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -5,18 +5,15 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle, Paul M. Antoine
+ * 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 <linux/linkage.h>
#include <asm/sgidefs.h>
+#include <linux/kernel.h>
-/*
- * sti/cli/save_flags use a memory clobber to make shure GCC doesn't
- * move memory references around calls to these functions.
- */
extern __inline__ void
sti(void)
{
@@ -24,20 +21,22 @@ sti(void)
".set\tnoreorder\n\t"
".set\tnoat\n\t"
"mfc0\t$1,$12\n\t"
- "ori\t$1,1\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");
+ : "$1", "memory");
}
/*
- * For cli() we have to make shure that the new c0_status value has
- * really arrived in the status register at the end of the inline
- * function using worst case scheduling. The worst case is the R4000
- * which needs three nops.
+ * 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)
@@ -56,7 +55,7 @@ cli(void)
".set\treorder"
: /* no outputs */
: /* no inputs */
- : "$1","memory");
+ : "$1", "memory");
}
#define save_flags(x) \
@@ -83,8 +82,6 @@ restore_flags(int flags)
: "memory");
}
-#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5)
#define sync_mem() \
__asm__ __volatile__( \
".set\tnoreorder\n\t" \
@@ -93,37 +90,24 @@ __asm__ __volatile__( \
: /* no output */ \
: /* no input */ \
: "memory")
-#else
-/*
- * FIXME: Don't really know what to do here for the R[236]000's.
- * Should probably bfc0 until write buffer is empty? - PMA
- * Not shure if wb flushing is really required but sounds reasonable.
- * The code below does this for R2000/R3000. - Ralf
- */
-#define sync_mem() \
-__asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;\n" \
- "1:\tbc0f\t1b\n\t" \
- "nop\n\t" \
- ".set\treorder" \
- : /* no output */ \
- : /* no input */ \
- : "memory")
-#endif
+#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.
*/
-struct task_struct;
-asmlinkage void resume(struct task_struct *tsk, int offset);
+extern asmlinkage void (*resume)(void *tsk);
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
/*
* FIXME: resume() assumes current == prev
*/
-#define switch_to(prev,next) \
- resume(next, ((int)(&((struct task_struct *)0)->tss)));
+#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.
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index 336915bce..7c981e6f7 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -38,15 +38,10 @@ struct termios {
#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 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]. */
-/* 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]. */
@@ -55,21 +50,14 @@ struct termios {
/*
* 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
- */
+#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. */
@@ -210,8 +198,8 @@ struct termios {
#define TCIOFLUSH 2 /* Discard all pending data. */
/* tcsetattr uses these */
-#define TCSANOW 0x540e /* Same as TCSETS; change immediately. */
-#define TCSADRAIN 0x540f /* Same as TCSETSW; change when pending output is written. */
-#define TCSAFLUSH 0x5410 /* Same as TCSETSF; flush pending input before changing. */
+#define TCSANOW TCSETS /* Change immediately. */
+#define TCSADRAIN TCSETSW /* Change when pending output is written. */
+#define TCSAFLUSH TCSETSF /* Flush pending input before changing. */
#endif /* __ASM_MIPS_TERMBITS_H */
diff --git a/include/asm-mips/termios.h b/include/asm-mips/termios.h
index 57fcbeef7..e62a60eab 100644
--- a/include/asm-mips/termios.h
+++ b/include/asm-mips/termios.h
@@ -61,11 +61,12 @@ struct termio {
#ifdef __KERNEL__
/*
* intr=^C quit=^\ erase=del kill=^U
- * eof=^D eol=time=\0 eol2=\0 swtc=\0
+ * 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\004\0\0\0\021\023\032\0\022\017\027\026"
+#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 */
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 48a205077..d71cb3fca 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -30,8 +30,10 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-#define get_fs() (current->tss.segment)
-#define set_fs(x) (current->tss.segment=(x))
+extern int active_ds;
+
+#define get_fs() active_ds
+#define set_fs(x) (active_ds=(x))
static inline unsigned long get_ds(void)
{
diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h
index 95eb47f55..ff7803316 100644
--- a/include/asm-mips/unaligned.h
+++ b/include/asm-mips/unaligned.h
@@ -10,52 +10,12 @@
#ifndef __ASM_MIPS_UNALIGNED_H
#define __ASM_MIPS_UNALIGNED_H
-#if 0
-/*
- * The following macros are the portable and efficient versions of
- * get_unaligned()/put_unaligned(). They work but due to some lackings in the
- * MIPS machine description of GCC generate only good code only for accessing
- * word sized data. We only use get_unaligned() for accessing unaligned ints
- * and then GCC makes full score anyway ...
- */
-#define get_unaligned(ptr) \
- ({ \
- struct __unal { \
- __typeof__(*(ptr)) __x __attribute__((packed)); \
- }; \
- \
- ((struct __unal *)(ptr))->__x; \
- })
-
-#define put_unaligned(ptr,val) \
- ({ \
- struct __unal { \
- __typeof__(*(ptr)) __x __attribute__((packed)); \
- }; \
- \
- ((struct __unal *)(ptr))->__x = (val); \
- })
-#else
-
-/*
- * The main single-value unaligned transfer routines.
- */
-#define get_unaligned(ptr) \
- ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
-#define put_unaligned(x,ptr) \
- __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
-
-/*
- * This is a silly but good way to make sure that
- * the get/put functions are indeed always optimized,
- * and that we use the correct sizes.
- */
-extern void bad_unaligned_access_length(void);
+#include <asm/string.h>
/*
- * Load unaligned doubleword.
+ * Load quad unaligned.
*/
-extern __inline__ unsigned long __uld(const unsigned long long * __addr)
+extern __inline__ unsigned long ldq_u(unsigned long long * __addr)
{
unsigned long long __res;
@@ -67,9 +27,9 @@ extern __inline__ unsigned long __uld(const unsigned long long * __addr)
}
/*
- * Load unaligned word.
+ * Load long unaligned.
*/
-extern __inline__ unsigned long __ulw(const unsigned int * __addr)
+extern __inline__ unsigned long ldl_u(unsigned int * __addr)
{
unsigned long __res;
@@ -81,9 +41,9 @@ extern __inline__ unsigned long __ulw(const unsigned int * __addr)
}
/*
- * Load unaligned halfword.
+ * Load word unaligned.
*/
-extern __inline__ unsigned long __ulh(const unsigned short * __addr)
+extern __inline__ unsigned long ldw_u(unsigned short * __addr)
{
unsigned long __res;
@@ -95,9 +55,9 @@ extern __inline__ unsigned long __ulh(const unsigned short * __addr)
}
/*
- * Store unaligned doubleword.
+ * Store quad ununaligned.
*/
-extern __inline__ void __usd(unsigned long __val, unsigned long long * __addr)
+extern __inline__ void stq_u(unsigned long __val, unsigned long long * __addr)
{
__asm__ __volatile__(
"usd\t%0,(%1)"
@@ -107,9 +67,9 @@ extern __inline__ void __usd(unsigned long __val, unsigned long long * __addr)
}
/*
- * Store unaligned word.
+ * Store long ununaligned.
*/
-extern __inline__ void __usw(unsigned long __val, unsigned int * __addr)
+extern __inline__ void stl_u(unsigned long __val, unsigned int * __addr)
{
__asm__ __volatile__(
"usw\t%0,(%1)"
@@ -119,9 +79,9 @@ extern __inline__ void __usw(unsigned long __val, unsigned int * __addr)
}
/*
- * Store unaligned halfword.
+ * Store word ununaligned.
*/
-extern __inline__ void __ush(unsigned long __val, unsigned short * __addr)
+extern __inline__ void stw_u(unsigned long __val, unsigned short * __addr)
{
__asm__ __volatile__(
"ush\t%0,(%1)"
@@ -130,47 +90,12 @@ extern __inline__ void __ush(unsigned long __val, unsigned short * __addr)
"r" (__addr));
}
-extern inline unsigned long __get_unaligned(const void *ptr, size_t size)
-{
- unsigned long val;
- switch (size) {
- case 1:
- val = *(const unsigned char *)ptr;
- break;
- case 2:
- val = __ulh((const unsigned short *)ptr);
- break;
- case 4:
- val = __ulw((const unsigned int *)ptr);
- break;
- case 8:
- val = __uld((const unsigned long long *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
- return val;
-}
+#define get_unaligned(ptr) \
+ ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-extern inline void __put_unaligned(unsigned long val, void *ptr, size_t size)
-{
- switch (size) {
- case 1:
- *(unsigned char *)ptr = (val);
- break;
- case 2:
- __ush(val, (unsigned short *)ptr);
- break;
- case 4:
- __usw(val, (unsigned int *)ptr);
- break;
- case 8:
- __usd(val, (unsigned long long *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
-}
-#endif
+#define put_unaligned(val, ptr) \
+ ({ __typeof__(*(ptr)) __tmp = (val); \
+ memcpy((ptr), &__tmp, sizeof(*(ptr))); \
+ (void)0; })
#endif /* __ASM_MIPS_UNALIGNED_H */
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 8db0d3cee..c62dad56b 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996 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
@@ -15,9 +15,8 @@
/*
* 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 ...
*/
/*
diff --git a/include/asm-mips/user.h b/include/asm-mips/user.h
index 64069dd60..e3747e88c 100644
--- a/include/asm-mips/user.h
+++ b/include/asm-mips/user.h
@@ -9,8 +9,8 @@
/*
* Core file format: The core file is written in such a way that gdb
* can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core). The file contents
- * are as follows:
+ * linux we use the `trad-core' bfd, NOT the irix-core). The file
+ * contents are as follows:
*
* upage: 1 page consisting of a user struct that tells gdb
* what is present in the file. Directly after this is a
@@ -30,7 +30,7 @@
* to write an integer number of pages.
*/
struct user {
- unsigned long regs[EF_SIZE/8+32]; /* integer and fp regs */
+ unsigned long regs[EF_SIZE/4+64]; /* integer and fp regs */
size_t u_tsize; /* text size (pages) */
size_t u_dsize; /* data size (pages) */
size_t u_ssize; /* stack size (pages) */
diff --git a/include/asm-mips/vector.h b/include/asm-mips/vector.h
index 23c5b8385..e3183b1de 100644
--- a/include/asm-mips/vector.h
+++ b/include/asm-mips/vector.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*/
#ifndef __ASM_MIPS_VECTOR_H
#define __ASM_MIPS_VECTOR_H
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index 3e738d382..b507d7a89 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -73,9 +73,4 @@ extern inline void * xchg_ptr(void * m, void * val)
return (void *) xchg_u32(m, (unsigned long) val);
}
-/*
- * Reset the machine.
- */
-extern void hard_reset_now(void);
-
#endif
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 43bbf1847..03c9c48fd 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -118,8 +118,6 @@ typedef unsigned long iopgprot_t;
#endif
-#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE)
-
extern unsigned long sparc_unmapped_base;
#define TASK_UNMAPPED_BASE (sparc_unmapped_base)
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 34800571c..1ec202c8e 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -242,9 +242,4 @@ static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
#endif /* __ASSEMBLY__ */
-/*
- * Reset the machine.
- */
-extern void hard_reset_now(void);
-
#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/include/linux/.cvsignore b/include/linux/.cvsignore
new file mode 100644
index 000000000..c4ff4db8f
--- /dev/null
+++ b/include/linux/.cvsignore
@@ -0,0 +1,3 @@
+autoconf.h
+version.h
+compile.h
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 6c424fbe9..6cb59427c 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -48,6 +48,7 @@ extern int read_exec(struct inode *inode, unsigned long offset,
extern int open_inode(struct inode * inode, int mode);
extern int init_elf_binfmt(void);
+extern int init_irix_binfmt(void);
extern int init_aout_binfmt(void);
extern int init_script_binfmt(void);
extern int init_java_binfmt(void);
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 3487041ba..726d0aa4b 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -56,18 +56,6 @@ typedef unsigned long Elf32_Word;
#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
#define EM_PARISC 15
-#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */
-
-#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
-
-#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
-
-#define EM_PARISC 15 /* HPPA */
-
-#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
-
-#define EM_PPC 20 /* PowerPC */
-
/*
* This is an interim value that we will use until the committee comes
* up with a final number.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0c64ed100..2283c278e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -616,18 +616,7 @@ extern int fsync_dev(kdev_t dev);
extern void sync_supers(kdev_t dev);
extern int bmap(struct inode * inode,int block);
extern int notify_change(struct inode *, struct iattr *);
-extern int _namei(const char * pathname, struct inode * base,
- int follow_links, struct inode ** res_inode);
extern int namei(const char * pathname, struct inode ** res_inode);
-/*
- * knamei() is the same as namei() except that it doesn't attempt
- * to copy the pathname from userspace to kernelspace. So it
- * can be used for names in kernelspace.
- */
-extern inline int knamei(const char *pathname, struct inode **res_inode)
-{
- return _namei(pathname, NULL, 1, res_inode);
-}
extern int lnamei(const char * pathname, struct inode ** res_inode);
extern int permission(struct inode * inode,int mask);
extern int get_write_access(struct inode *inode);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 535cdefdc..44e600fc3 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -21,6 +21,10 @@
#define CONFIG_SUN_PARTITION 1
#endif
+#if defined(CONFIG_SGI)
+#define CONFIG_SGI_PARTITION 1
+#endif
+
/* These two have identical behaviour; use the second one if DOS fdisk gets
confused about extended/logical partitions starting past cylinder 1023. */
#define DOS_EXTENDED_PARTITION 5
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 9349f0f49..88824df8a 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -3,7 +3,7 @@
#include <linux/types.h>
-#define IPC_PRIVATE ((__kernel_key_t) 0)
+#define IPC_PRIVATE ((key_t) 0)
struct ipc_perm
{
@@ -12,7 +12,7 @@ struct ipc_perm
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
- __kernel_mode_t mode;
+ __kernel_mode_t mode;
unsigned short seq;
};
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 149e6eaeb..6af5f2401 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -222,20 +222,6 @@ typedef struct page {
extern mem_map_t * mem_map;
/*
- * Free area management
- */
-
-#define NR_MEM_LISTS 6
-
-struct mem_list {
- struct mem_list * next;
- struct mem_list * prev;
-};
-
-extern struct mem_list free_area_list[NR_MEM_LISTS];
-extern unsigned int * free_area_map[NR_MEM_LISTS];
-
-/*
* This is timing-critical - most of the time in getting a new page
* goes to clearing the page. If you want a page without the clearing
* overhead, just use __get_free_page() directly..
diff --git a/include/linux/msg.h b/include/linux/msg.h
index 2be627198..deda19265 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -58,6 +58,10 @@ struct msginfo {
#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
#define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
+/* ipcs ctl commands */
+#define MSG_STAT 11
+#define MSG_INFO 12
+
#ifdef __KERNEL__
/* one msg structure for each message */
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 22cec7aaa..61db37850 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -74,8 +74,8 @@ struct mtget {
long mt_gstat; /* generic (device independent) status */
long mt_erreg; /* error register */
/* The next two fields are not always used */
- __kernel_daddr_t mt_fileno; /* number of current file on tape */
- __kernel_daddr_t mt_blkno; /* current block number */
+ __kernel_daddr_t mt_fileno; /* number of current file on tape */
+ __kernel_daddr_t mt_blkno; /* current block number */
};
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 91538d2bd..c8f09ebea 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -21,6 +21,9 @@
#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
#define PER_BSD (0x0006)
#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
+#define PER_IRIX32 (0x0008 | STICKY_TIMEOUTS) /* IRIX5 32-bit */
+#define PER_IRIXN32 (0x0009 | STICKY_TIMEOUTS) /* IRIX6 new 32-bit */
+#define PER_IRIX64 (0x000a | STICKY_TIMEOUTS) /* IRIX6 64-bit */
/* Prototype for an lcall7 syscall handler. */
typedef asmlinkage void (*lcall7_func)(struct pt_regs *);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 42ad7cacb..2bb90e3f5 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -147,6 +147,7 @@ enum scsi_directory_inos {
PROC_SCSI_A2091,
PROC_SCSI_GVP11,
PROC_SCSI_ATARI,
+ PROC_SCSI_SGIWD93,
PROC_SCSI_SCSI_DEBUG,
PROC_SCSI_NOT_PRESENT,
PROC_SCSI_FILE, /* I'm assuming here that we */
diff --git a/include/linux/string.h b/include/linux/string.h
index 214503c20..5eb5cc50a 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -13,7 +13,7 @@ extern "C" {
extern char * ___strtok;
extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
+extern char * strncpy(char *,const char *,__kernel_size_t);
extern char * strcat(char *, const char *);
extern char * strncat(char *, const char *, __kernel_size_t);
extern char * strchr(const char *,int);
@@ -27,7 +27,7 @@ extern __kernel_size_t strspn(const char *,const char *);
extern int strcmp(const char *,const char *);
extern int strncmp(const char *,const char *,__kernel_size_t);
-extern void * memset(void *,int,__kernel_size_t);
+extern void * memset(void *,char,__kernel_size_t);
extern void * memcpy(void *,const void *,__kernel_size_t);
extern void * memmove(void *,const void *,__kernel_size_t);
extern void * memscan(void *,int,__kernel_size_t);
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 89e42d849..ae6a063e3 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -17,8 +17,6 @@
#ifndef _LINUX_TCP_H
#define _LINUX_TCP_H
-#include <asm/byteorder.h>
-
#include <linux/types.h>
#include <asm/byteorder.h>
diff --git a/include/linux/time.h b/include/linux/time.h
index 47246a142..7482f8e2e 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -3,10 +3,12 @@
#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
+#ifdef __KERNEL__
struct timespec {
long tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
+#endif /* (__KERNEL__) */
#endif /* _STRUCT_TIMESPEC */
struct timeval {
@@ -28,11 +30,13 @@ void get_fast_time(struct timeval *tv);
void (*do_get_fast_time)(struct timeval *);
#endif
+#ifdef __KERNEL__
#define FD_SETSIZE __FD_SETSIZE
#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp)
#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp)
#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp)
#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp)
+#endif
/*
* Names of the interval timers, and structure
diff --git a/include/linux/tty.h b/include/linux/tty.h
index c965cd287..04c78e1ae 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -78,6 +78,8 @@ extern struct screen_info screen_info;
#define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */
+#define VIDEO_TYPE_SGI 0x60 /* Various SGI graphics hardware */
+
/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
* a c_cc[] character, but indicates that a particular special character
diff --git a/init/main.c b/init/main.c
index 30ecc97d5..90d3f8f71 100644
--- a/init/main.c
+++ b/init/main.c
@@ -39,6 +39,9 @@
#include <stdarg.h>
+#ifdef CONFIG_SGI
+#include <asm/sgialib.h>
+#endif
/*
* Versions of gcc older than that listed below may actually compile
@@ -50,10 +53,6 @@
#error sorry, your GCC is too old. It builds incorrect kernels.
#endif
-#ifdef CONFIG_MIPS_JAZZ
-#include <asm/jazz.h>
-#endif
-
extern char _stext, _etext;
extern char *linux_banner;
@@ -194,6 +193,8 @@ extern void ipc_init(void);
#include <asm/gdb-stub.h>
#endif
+extern int serial_console;
+
/*
* Boot command-line arguments
*/
@@ -419,7 +420,7 @@ struct {
{ "atascsi=", atari_scsi_setup },
#endif
#if defined(CONFIG_A3000_SCSI) || defined(CONFIG_A2091_SCSI) \
- || defined(CONFIG_GVP11_SCSI)
+ || defined(CONFIG_GVP11_SCSI) || defined(CONFIG_SCSI_SGIWD93)
{ "wd33c93=", wd33c93_setup },
#endif
#if defined(CONFIG_GVP11_SCSI)
@@ -827,7 +828,7 @@ asmlinkage void start_kernel(void)
memory_start = console_init(memory_start,memory_end);
#ifdef CONFIG_REMOTE_DEBUG
set_debug_traps();
-/* breakpoint(); */ /* execute a BREAK insn */
+ /* breakpoint(); */ /* execute a BREAK insn */
#endif
#ifdef CONFIG_PCI
memory_start = pci_init(memory_start,memory_end);
@@ -905,7 +906,13 @@ static int do_shell(void * shell)
close(0);close(1);close(2);
setsid();
- (void) open("/dev/tty1",O_RDWR,0);
+ if (serial_console == 1) {
+ (void) open("/dev/ttyS0",O_RDWR,0);
+ } else if (serial_console == 2) {
+ (void) open("/dev/ttyS1",O_RDWR,0);
+ } else {
+ (void) open("/dev/tty1",O_RDWR,0);
+ }
(void) dup(0);
(void) dup(0);
argv[0] = shell;
@@ -921,6 +928,17 @@ static int do_linuxrc(void * shell)
close(0);close(1);close(2);
setsid();
(void) open("/dev/tty1",O_RDWR,0);
+
+ /*
+ * This keeps serial console MUCH cleaner, but does assume
+ * the console driver checks there really is a video device
+ * attached (Sparc effectively does).
+ */
+
+ if ((open("/dev/tty1",O_RDWR,0) < 0) &&
+ (open("/dev/ttyS0",O_RDWR,0) < 0))
+ printk("Unable to open an initial console.\n");
+
(void) dup(0);
(void) dup(0);
return execve(shell, argv, envp_init);
@@ -992,17 +1010,14 @@ static int init(void * unused)
}
}
#endif
-
- /*
- * This keeps serial console MUCH cleaner, but does assume
- * the console driver checks there really is a video device
- * attached (Sparc effectively does).
- */
- if ((open("/dev/tty1",O_RDWR,0) < 0) &&
- (open("/dev/ttyS0",O_RDWR,0) < 0))
- printk("Unable to open an initial console.\n");
-
+ if (serial_console == 1) {
+ (void) open("/dev/cua0",O_RDWR,0);
+ } else if(serial_console == 2) {
+ (void) open("/dev/cua1",O_RDWR,0);
+ } else {
+ (void) open("/dev/tty1",O_RDWR,0);
+ }
(void) dup(0);
(void) dup(0);
diff --git a/ipc/.cvsignore b/ipc/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/ipc/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/kernel/.cvsignore b/kernel/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/kernel/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/kernel/exit.c b/kernel/exit.c
index d2fdbdc4a..d4c54209d 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -475,6 +475,9 @@ static inline void __exit_mm(struct task_struct * tsk)
if (mm != &init_mm) {
flush_cache_mm(mm);
flush_tlb_mm(mm);
+#ifdef __mips__
+ mm->context = 0;
+#endif
tsk->mm = &init_mm;
tsk->swappable = 0;
SET_PAGE_DIR(tsk, swapper_pg_dir);
@@ -712,12 +715,3 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
}
#endif
-
-/*
- * sys_wait() has been added for compatibility. wait() should be
- * implemented by calling sys_wait4() from libc.a.
- */
-asmlinkage int sys_wait(unsigned int * stat_addr)
-{
- return sys_wait4(-1, stat_addr, 0, NULL);
-}
diff --git a/kernel/fork.c b/kernel/fork.c
index 864bc52e8..b81d98e77 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -118,6 +118,9 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
if (!mm)
return -1;
*mm = *current->mm;
+#ifdef __mips__
+ mm->context = 0;
+#endif
mm->count = 1;
mm->def_flags = 0;
tsk->mm = mm;
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index a612201c0..b694cd6d2 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -81,6 +81,8 @@ extern int sys_tz;
extern int request_dma(unsigned int dmanr, char * deviceID);
extern void free_dma(unsigned int dmanr);
+extern void hard_reset_now(void);
+
struct symbol_table symbol_table = {
#include <linux/symtab_begin.h>
#ifdef MODVERSIONS
diff --git a/kernel/panic.c b/kernel/panic.c
index 7e04fdc31..d42541e9f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -7,15 +7,15 @@
/*
* This function is used through-out the kernel (including mm and fs)
* to indicate a major problem.
- * Support for machines without PC-style console hardware - <dfrick@dial.eunet.ch>, July 96
*/
#include <stdarg.h>
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
-#include <linux/config.h>
-#include <asm/system.h>
+
+#include <asm/sgialib.h>
asmlinkage void sys_sync(void); /* it's really int */
extern void do_unblank_screen(void);
@@ -33,7 +33,6 @@ NORET_TYPE void panic(const char * fmt, ...)
{
static char buf[1024];
va_list args;
- int i;
va_start(args, fmt);
vsprintf(buf, fmt, args);
@@ -44,21 +43,28 @@ NORET_TYPE void panic(const char * fmt, ...)
else
sys_sync();
-#ifndef CONFIG_SERIAL_ONLY_CONSOLE
do_unblank_screen();
-#endif
+#ifdef CONFIG_SGI
if (panic_timeout > 0)
{
+ int i;
+
/*
* Delay timeout seconds before rebooting the machine.
* We can't use the "normal" timers since we just panicked..
*/
- printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
+ prom_printf(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
for(i = 0; i < (panic_timeout*1000); i++)
udelay(1000);
hard_reset_now();
}
+#if 0
+ printk("Hit a key\n");
+ prom_getchar();
+ romvec->imode();
+#endif
+#endif
for(;;);
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 8f88f88a3..98502b3fc 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -126,7 +126,8 @@ static inline void add_to_runqueue(struct task_struct * p)
init_task.prev_run = p;
#ifdef __SMP__
/* this is safe only if called with cli()*/
- while(set_bit(31,&smp_process_available))
+ while(set_bit(31,&smp_process_available));
+#if 0
{
while(test_bit(31,&smp_process_available))
{
@@ -137,6 +138,7 @@ static inline void add_to_runqueue(struct task_struct * p)
}
}
}
+#endif
smp_process_available++;
clear_bit(31,&smp_process_available);
if ((0!=p->pid) && smp_threads_ready)
@@ -410,11 +412,6 @@ asmlinkage void schedule(void)
scheduling_in_interrupt:
printk("Aiee: scheduling in interrupt %p\n",
return_address());
-/*
- * System is probably fucked up anyway beyond a save landing; prevent
- * messages on the screen from scrolling away.
- */
-while(1);
}
#ifndef __alpha__
@@ -488,7 +485,7 @@ void wake_up_interruptible(struct wait_queue **q)
return;
bad:
printk("wait_queue is bad (eip = %p)\n",
- __builtin_return_address(0));
+ return_address());
printk(" q = %p\n",q);
printk(" *q = %p\n",*q);
}
diff --git a/kernel/sys.c b/kernel/sys.c
index b2cc8f154..8fcaba2de 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -27,7 +27,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/system.h>
/*
* this indicates whether you can reboot with ctrl-alt-del: the default is yes
diff --git a/lib/.cvsignore b/lib/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/lib/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index f1adf6fc2..8f813c655 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -59,27 +59,14 @@ static int skip_atoi(const char **s)
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-#ifdef __mips64
-#define do_div(n,base) ({ \
-long long __res; \
-__res = ((unsigned long long) n) % (unsigned long long) base; \
-n = ((unsigned long long) n) / (unsigned long long) base; \
-__res; })
-#else
#define do_div(n,base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
__res; })
-#endif
-#ifdef __mips64
-static char * number(char * str, long long num, int base, int size, int precision
- ,int type)
-#else
static char * number(char * str, long num, int base, int size, int precision
,int type)
-#endif
{
char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
@@ -147,11 +134,7 @@ static char * number(char * str, long num, int base, int size, int precision
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
-#ifdef __mips64
- unsigned long long num;
-#else
unsigned long num;
-#endif
int i, base;
char * str;
const char *s;
@@ -261,9 +244,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
- } else if (qualifier == 'L') {
- long long * ip = va_arg(args, long long *);
- *ip = (str - buf);
} else {
int * ip = va_arg(args, int *);
*ip = (str - buf);
@@ -303,11 +283,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
num = va_arg(args, short);
else
num = va_arg(args, unsigned short);
- else if (qualifier == 'L')
- if (flags & SIGN)
- num = va_arg(args, long long);
- else
- num = va_arg(args, unsigned long long);
else if (flags & SIGN)
num = va_arg(args, int);
else
diff --git a/log b/log
deleted file mode 100644
index 548fe53c9..000000000
--- a/log
+++ /dev/null
@@ -1,19 +0,0 @@
-mipsel-linux-gcc -D__KERNEL__ -I/usr/home/ralf/src/linux-2.1.10/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -mcpu=r4400 -mips3 -DUTS_MACHINE='"mips"' -c -o init/version.o init/version.c
-set -e; for i in arch/mips/mips3; do make -C $i; done
-make[1]: Entering directory `/usr/home/ralf/src/linux-2.1.10/arch/mips/mips3'
-mipsel-linux-gcc -D__KERNEL__ -I/usr/home/ralf/src/linux-2.1.10/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -mcpu=r4400 -mips3 -c copy_user.S -o copy_user.o
-rm -f mips.o
-mipsel-linux-ld -r -o mips.o cache.o copy_user.o cpu.o fp-context.o memset.o r4xx0.o pagetables.o showregs.o
-make[1]: Leaving directory `/usr/home/ralf/src/linux-2.1.10/arch/mips/mips3'
-mipsel-linux-ld -N -G 0 -T arch/mips/ld.script -Ttext 0x80000000 -Ttext 0x80000000 arch/mips/kernel/head.o init/main.o init/version.o \
- arch/mips/mips3/mips.o arch/mips/kernel/kernel.o arch/mips/mm/mm.o kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o net/network.a arch/mips/jazz/jazz.o arch/mips/sni/sni.o \
- fs/filesystems.a \
- drivers/block/block.a drivers/char/char.a drivers/net/net.a drivers/scsi/scsi.a drivers/cdrom/cdrom.a \
- arch/mips/lib/lib.a /usr/home/ralf/src/linux-2.1.10/lib/lib.a arch/mips/lib/lib.a -o vmlinux
-mipsel-linux-nm vmlinux | grep -v '\(compiled\)\|\(\.o$\)\|\( a \)\|\(\$\)' | sort > System.map
-make[1]: Entering directory `/usr/home/ralf/src/linux-2.1.10/arch/mips/boot'
-mipsel-linux-objcopy --remove-section=.reginfo --remove-section=.mdebug /usr/home/ralf/src/linux-2.1.10/vmlinux zImage.tmp
-./mkboot zImage.tmp zImage
-rm -f zImage.tmp
-mcopy -n zImage a:vmlinux
-make[1]: Leaving directory `/usr/home/ralf/src/linux-2.1.10/arch/mips/boot'
diff --git a/mm/.cvsignore b/mm/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/mm/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/mm/kmalloc.c b/mm/kmalloc.c
index d0193f02b..960b9f581 100644
--- a/mm/kmalloc.c
+++ b/mm/kmalloc.c
@@ -20,9 +20,6 @@
#include <asm/system.h>
#include <asm/dma.h>
-#ifdef __mips__
-#include <asm/sgidefs.h>
-#endif
/* Define this if you want slow routines that try to trip errors */
#undef SADISTIC_KMALLOC
@@ -95,51 +92,10 @@ struct size_descriptor {
/*
* For now it is unsafe to allocate bucket sizes between n and
* n-sizeof(page_descriptor) where n is PAGE_SIZE * any power of two
+ *
+ * The blocksize and sizes arrays _must_ match!
*/
-#if PAGE_SIZE == 4096 && defined (__mips__) && \
- ((_MIPS_ISA == _MIPS_ISA_MIPS2) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS3) || \
- (_MIPS_ISA == _MIPS_ISA_MIPS4))
-static const unsigned int blocksize[] = {
- /*
- * For MIPS II we need this hacked descriptor table to get
- * doubleword alignment. Otherwise the scheduler and other code
- * that use doublewords will bomb.
- */
- 32,
- 64,
- 128,
- 248,
- 504,
- 1016,
- 2040,
- 4096 - 16,
- 8192 - 16,
- 16384 - 16,
- 32768 - 16,
- 65536 - 16,
- 131072 - 16,
- 0
-};
-
-static struct size_descriptor sizes[] =
-{
- {NULL, NULL, 127, 0, 0, 0, 0, 0},
- {NULL, NULL, 63, 0, 0, 0, 0, 0},
- {NULL, NULL, 31, 0, 0, 0, 0, 0},
- {NULL, NULL, 16, 0, 0, 0, 0, 0},
- {NULL, NULL, 8, 0, 0, 0, 0, 0},
- {NULL, NULL, 4, 0, 0, 0, 0, 0},
- {NULL, NULL, 2, 0, 0, 0, 0, 0},
- {NULL, NULL, 1, 0, 0, 0, 0, 0},
- {NULL, NULL, 1, 0, 0, 0, 0, 1},
- {NULL, NULL, 1, 0, 0, 0, 0, 2},
- {NULL, NULL, 1, 0, 0, 0, 0, 3},
- {NULL, NULL, 1, 0, 0, 0, 0, 4},
- {NULL, NULL, 1, 0, 0, 0, 0, 5},
- {NULL, NULL, 0, 0, 0, 0, 0, 0}
-};
-#elif PAGE_SIZE == 4096
+#if PAGE_SIZE == 4096
static const unsigned int blocksize[] = {
32,
64,
@@ -189,7 +145,7 @@ static const unsigned int blocksize[] = {
65536 - 32,
131072 - 32,
262144 - 32,
- 0
+ 0
};
struct size_descriptor sizes[] =
@@ -216,29 +172,6 @@ struct size_descriptor sizes[] =
#define NBLOCKS(order) (sizes[order].nblocks)
#define BLOCKSIZE(order) (blocksize[order])
#define AREASIZE(order) (PAGE_SIZE<<(sizes[order].gfporder))
-
-
-long kmalloc_init(long start_mem, long end_mem)
-{
- int order;
-
-/*
- * Check the static info array. Things will blow up terribly if it's
- * incorrect. This is a late "compile time" check.....
- */
- for (order = 0; BLOCKSIZE(order); order++) {
- if ((NBLOCKS(order) * BLOCKSIZE(order) + sizeof(struct page_descriptor)) >
- AREASIZE(order)) {
- printk("Cannot use %d bytes out of %d in order = %d block mallocs\n",
- (int) (NBLOCKS(order) * BLOCKSIZE(order) +
- sizeof(struct page_descriptor)),
- (int) AREASIZE(order),
- BLOCKSIZE(order));
- panic("This only happens if someone messes with kmalloc");
- }
- }
- return start_mem;
-}
/*
* Create a small cache of page allocations: this helps a bit with
@@ -268,6 +201,29 @@ static inline void free_kmalloc_pages(struct page_descriptor * page,
free_pages((unsigned long) page, order);
}
+long kmalloc_init(long start_mem, long end_mem)
+{
+ int order;
+
+/*
+ * Check the static info array. Things will blow up terribly if it's
+ * incorrect. This is a late "compile time" check.....
+ */
+ for (order = 0; BLOCKSIZE(order); order++) {
+ if ((NBLOCKS(order) * BLOCKSIZE(order) + sizeof(struct page_descriptor)) >
+ AREASIZE(order)) {
+ printk("Cannot use %d bytes out of %d in order = %d block mallocs\n",
+ (int) (NBLOCKS(order) * BLOCKSIZE(order) +
+ sizeof(struct page_descriptor)),
+ (int) AREASIZE(order),
+ BLOCKSIZE(order));
+ panic("This only happens if someone messes with kmalloc");
+ }
+ }
+ return start_mem;
+}
+
+
/*
* Ugh, this is ugly, but we want the default case to run
* straight through, which is why we have the ugly goto's
diff --git a/mm/mmap.c b/mm/mmap.c
index ac245a17f..a264e319b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -45,7 +45,7 @@ pgprot_t protection_map[16] = {
* Check that a process has enough memory to allocate a
* new virtual mapping.
*/
-static inline int vm_enough_memory(long pages)
+int vm_enough_memory(long pages)
{
/*
* stupid algorithm to decide if we have enough memory: while
diff --git a/net/.cvsignore b/net/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/802/.cvsignore b/net/802/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/802/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/appletalk/.cvsignore b/net/appletalk/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/appletalk/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/ax25/.cvsignore b/net/ax25/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/ax25/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/bridge/.cvsignore b/net/bridge/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/bridge/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/core/.cvsignore b/net/core/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/core/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/ethernet/.cvsignore b/net/ethernet/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/ethernet/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/ipv4/.cvsignore b/net/ipv4/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/ipv4/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/ipx/.cvsignore b/net/ipx/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/ipx/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/netrom/.cvsignore b/net/netrom/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/netrom/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/net/unix/.cvsignore b/net/unix/.cvsignore
new file mode 100644
index 000000000..4671378ae
--- /dev/null
+++ b/net/unix/.cvsignore
@@ -0,0 +1 @@
+.depend