summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/ptrace.c5
-rw-r--r--arch/mips/kernel/signal.c8
-rw-r--r--arch/mips/kernel/traps.c47
-rw-r--r--arch/mips/lib/csum_partial_copy.S519
-rw-r--r--arch/mips/lib/csum_partial_copy.c59
-rw-r--r--arch/mips/lib/memcpy.S6
-rw-r--r--arch/mips/sgi/kernel/indy_hpc.c28
-rw-r--r--arch/mips/sgi/kernel/reset.c185
-rw-r--r--arch/mips/sgi/kernel/setup.c18
-rw-r--r--arch/mips/sgi/prom/misc.c8
10 files changed, 280 insertions, 603 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4112c0006..f9172b726 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -68,6 +68,7 @@ repeat:
*/
flush_cache_all();
retval = *(unsigned long *) page;
+ flush_cache_all(); /* VCED avoidance */
return retval;
}
@@ -122,10 +123,10 @@ repeat:
}
/* This is a hack for non-kernel-mapped video buffers and similar */
if (MAP_NR(page) < MAP_NR(high_memory))
- flush_cache_page(vma, addr);
+ flush_cache_all();
*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
if (MAP_NR(page) < MAP_NR(high_memory))
- flush_page_to_ram(page);
+ flush_cache_all();
/*
* We're bypassing pagetables, so we have to set the dirty bit
* ourselves this should also re-instate whatever read-only mode
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 3457caf1b..6b9fd263e 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -4,7 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, 1995, 1996 Ralf Baechle
*
- * $Id: signal.c,v 1.13 1998/07/03 23:05:37 ralf Exp $
+ * $Id: signal.c,v 1.14 1998/07/04 00:49:51 ralf Exp $
*
* XXX Handle lazy fp context switches correctly.
*/
@@ -55,7 +55,8 @@ sys_sigsuspend(struct pt_regs regs)
current->blocked = newset;
spin_unlock_irq(&current->sigmask_lock);
- regs.regs[2] = -EINTR;
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -80,7 +81,8 @@ sys_rt_sigsuspend(struct pt_regs regs)
current->blocked = newset;
spin_unlock_irq(&current->sigmask_lock);
- regs.regs[2] = -EINTR;
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2d1fbcd96..7d5a703f6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.14 1998/05/28 03:17:56 ralf Exp $
+/* $Id: traps.c,v 1.12 1998/06/30 00:21:53 ralf Exp $
*
* 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
@@ -24,8 +24,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#undef CONF_DEBUG_EXCEPTIONS
-
static inline void console_verbose(void)
{
extern int console_loglevel;
@@ -196,9 +194,6 @@ show_regs(regs); while(1);
void do_ov(struct pt_regs *regs)
{
lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
if (compute_return_epc(regs))
goto out;
force_sig(SIGFPE, current);
@@ -238,9 +233,6 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
}
#endif
lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
if (fcr31 & 0x20000) {
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
@@ -282,41 +274,28 @@ static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
return 0;
}
-static inline void
-do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode)
-{
- /*
- * (A short test says that IRIX 5.3 sends SIGTRAP for all break
- * insns, even for break codes that indicate arithmetic failures.
- * Wiered ...)
- */
- force_sig(SIGTRAP, current);
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
-}
void do_bp(struct pt_regs *regs)
{
unsigned int opcode, bcode;
- lock_kernel();
/*
* There is the ancient bug in the MIPS assemblers that the break
* code starts left to bit 16 instead to bit 6 in the opcode.
* Gas is bug-compatible ...
*/
-#ifdef CONF_DEBUG_EXCEPTIONS
- printk("BREAKPOINT at %08lx\n", regs->cp0_epc);
-#endif
if (get_insn_opcode(regs, &opcode))
goto out;
bcode = ((opcode >> 16) & ((1 << 20) - 1));
- do_bp_and_tr(regs, "bp", bcode);
+ lock_kernel();
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Wiered ...)
+ */
+ force_sig(SIGTRAP, current);
- if (compute_return_epc(regs))
- goto out;
out:
unlock_kernel();
}
@@ -330,7 +309,12 @@ void do_tr(struct pt_regs *regs)
goto out;
bcode = ((opcode >> 6) & ((1 << 20) - 1));
- do_bp_and_tr(regs, "tr", bcode);
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Wiered ...)
+ */
+ force_sig(SIGTRAP, current);
out:
unlock_kernel();
}
@@ -338,9 +322,6 @@ out:
void do_ri(struct pt_regs *regs)
{
lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
if (compute_return_epc(regs))
diff --git a/arch/mips/lib/csum_partial_copy.S b/arch/mips/lib/csum_partial_copy.S
deleted file mode 100644
index d5b281574..000000000
--- a/arch/mips/lib/csum_partial_copy.S
+++ /dev/null
@@ -1,519 +0,0 @@
-/* $Id: csum_partial_copy.S,v 1.5 1998/05/06 02:43:34 ralf Exp $
- *
- * Unified implementation of csum_copy_partial, csum_copy_partial_from_user
- * and csum_copy_partial_nocheck.
- *
- * 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) 1998 Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-
-/*
- * The fixup routine for csum_partial_copy_from_user depends on copying
- * strictly in increasing order. Gas expands ulw/usw macros in the wrong order
- * for little endian machines, so we cannot depend on them.
- */
-#ifdef __MIPSEB__
-#define ulwL lwl
-#define ulwU lwr
-#endif
-#ifdef __MIPSEL__
-#define ulwL lwr
-#define ulwU lwl
-#endif
-
-#define EX(insn,reg,addr,handler) \
-9: insn reg, addr; \
- .section __ex_table,"a"; \
- PTR 9b, handler; \
- .previous
-
-#define UEX(insn,reg,addr,handler) \
-9: insn ## L reg, addr; \
-10: insn ## U reg, 3 + addr; \
- .section __ex_table,"a"; \
- PTR 9b, handler; \
- PTR 10b, handler; \
- .previous
-
-#define ADDC(sum,reg) \
- addu sum, reg; \
- sltu v1, sum, reg; \
- addu sum, v1
-
-/* ascending order, destination aligned */
-#define CSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \
- EX(lw, t0, (offset + 0x00)(src), l_fixup); \
- EX(lw, t1, (offset + 0x04)(src), l_fixup); \
- EX(lw, t2, (offset + 0x08)(src), l_fixup); \
- EX(lw, t3, (offset + 0x0c)(src), l_fixup); \
- ADDC(sum, t0); \
- ADDC(sum, t1); \
- ADDC(sum, t2); \
- ADDC(sum, t3); \
- sw t0, (offset + 0x00)(dst); \
- sw t1, (offset + 0x04)(dst); \
- sw t2, (offset + 0x08)(dst); \
- sw t3, (offset + 0x0c)(dst); \
- EX(lw, t0, (offset + 0x10)(src), l_fixup); \
- EX(lw, t1, (offset + 0x14)(src), l_fixup); \
- EX(lw, t2, (offset + 0x18)(src), l_fixup); \
- EX(lw, t3, (offset + 0x1c)(src), l_fixup); \
- ADDC(sum, t0); \
- ADDC(sum, t1); \
- ADDC(sum, t2); \
- ADDC(sum, t3); \
- sw t0, (offset + 0x10)(dst); \
- sw t1, (offset + 0x14)(dst); \
- sw t2, (offset + 0x18)(dst); \
- sw t3, (offset + 0x1c)(dst)
-
-/* ascending order, destination unaligned */
-#define UCSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \
- EX(lw, t0, (offset + 0x00)(src), l_fixup); \
- EX(lw, t1, (offset + 0x04)(src), l_fixup); \
- EX(lw, t2, (offset + 0x08)(src), l_fixup); \
- EX(lw, t3, (offset + 0x0c)(src), l_fixup); \
- ADDC(sum, t0); \
- ADDC(sum, t1); \
- ADDC(sum, t2); \
- ADDC(sum, t3); \
- usw t0, (offset + 0x00)(dst); \
- usw t1, (offset + 0x04)(dst); \
- usw t2, (offset + 0x08)(dst); \
- usw t3, (offset + 0x0c)(dst); \
- EX(lw, t0, (offset + 0x00)(src), l_fixup); \
- EX(lw, t1, (offset + 0x04)(src), l_fixup); \
- EX(lw, t2, (offset + 0x08)(src), l_fixup); \
- EX(lw, t3, (offset + 0x0c)(src), l_fixup); \
- ADDC(sum, t0); \
- ADDC(sum, t1); \
- ADDC(sum, t2); \
- ADDC(sum, t3); \
- usw t0, (offset + 0x10)(dst); \
- usw t1, (offset + 0x14)(dst); \
- usw t2, (offset + 0x18)(dst); \
- usw t3, (offset + 0x1c)(dst)
-
-#
-# a0: source address
-# a1: destination address
-# a2: length of the area to checksum
-# a3: partial checksum
-#
-
-#define src a0
-#define dest a1
-#define sum v0
-
- .text
- .set noreorder
-
-/* unknown src/dst alignment and < 8 bytes to go */
-small_csumcpy:
- move a2, t2
-
- andi t0, a2, 4
- beqz t0, 1f
- andi t0, a2, 2
-
- /* Still a full word to go */
- UEX(ulw, t1, 0(src), l_fixup)
- addiu src, 4
- usw t1, 0(dest)
- addiu dest, 4
- ADDC(sum, t1)
-
-1: move t1, zero
- beqz t0, 1f
- andi t0, a2, 1
-
- /* Still a halfword to go */
- ulhu t1, (src)
- addiu src, 2
- ush t1, (dest)
- addiu dest, 2
-
-1: beqz t0, 1f
- sll t1, t1, 16
-
- lbu t2, (src)
- nop
- sb t2, (dest)
-
-#ifdef __MIPSEB__
- sll t2, t2, 8
-#endif
- or t1, t2
-
-1: ADDC(sum, t1)
-
- /* fold checksum */
- sll v1, sum, 16
- addu sum, v1
- sltu v1, sum, v1
- srl sum, sum, 16
- addu sum, v1
-
- /* odd buffer alignment? */
- beqz t7, 1f
- nop
- sll v1, sum, 8
- srl sum, sum, 8
- or sum, v1
- andi sum, 0xffff
-1:
- .set reorder
- /* Add the passed partial csum. */
- ADDC(sum, a3)
- jr ra
- .set noreorder
-
-/* ------------------------------------------------------------------------- */
-
- .align 5
-LEAF(csum_partial_copy_from_user)
- addu t5, src, a2 # end address for fixup
-EXPORT(csum_partial_copy_nocheck)
-EXPORT(csum_partial_copy)
- move sum, zero # clear computed sum
- move t7, zero # clear odd flag
- xor t0, dest, src
- andi t0, t0, 0x3
- beqz t0, can_align
- sltiu t8, a2, 0x8
-
- b memcpy_u_src # bad alignment
- move t2, a2
-
-can_align:
- bnez t8, small_csumcpy # < 8 bytes to copy
- move t2, a2
-
- beqz a2, out
- andi t7, src, 0x1 # odd buffer?
-
-hword_align:
- beqz t7, word_align
- andi t8, src, 0x2
-
- EX(lbu, t0, (src), l_fixup)
- subu a2, a2, 0x1
- EX(sb, t0, (dest), l_fixup)
-#ifdef __MIPSEL__
- sll t0, t0, 8
-#endif
- ADDC(sum, t0)
- addu src, src, 0x1
- addu dest, dest, 0x1
- andi t8, src, 0x2
-
-word_align:
- beqz t8, dword_align
- sltiu t8, a2, 56
-
- EX(lhu, t0, (src), l_fixup)
- subu a2, a2, 0x2
- sh t0, (dest)
- ADDC(sum, t0)
- sltiu t8, a2, 56
- addu dest, dest, 0x2
- addu src, src, 0x2
-
-dword_align:
- bnez t8, do_end_words
- move t8, a2
-
- andi t8, src, 0x4
- beqz t8, qword_align
- andi t8, src, 0x8
-
- EX(lw, t0, 0x00(src), l_fixup)
- subu a2, a2, 0x4
- ADDC(sum, t0)
- sw t0, 0x00(dest)
- addu src, src, 0x4
- addu dest, dest, 0x4
- andi t8, src, 0x8
-
-qword_align:
- beqz t8, oword_align
- andi t8, src, 0x10
-
- EX(lw, t0, 0x00(src), l_fixup)
- EX(lw, t1, 0x04(src), l_fixup)
- subu a2, a2, 0x8
- ADDC(sum, t0)
- ADDC(sum, t1)
- sw t0, 0x00(dest)
- addu src, src, 0x8
- sw t1, 0x04(dest)
- andi t8, src, 0x10
- addu dest, dest, 0x8
-
-oword_align:
- beqz t8, begin_movement
- srl t8, a2, 0x7
-
- EX(lw, t3, 0x08(src), l_fixup) # assumes subblock ordering
- EX(lw, t4, 0x0c(src), l_fixup)
- EX(lw, t0, 0x00(src), l_fixup)
- EX(lw, t1, 0x04(src), l_fixup)
- ADDC(sum, t3)
- ADDC(sum, t4)
- ADDC(sum, t0)
- ADDC(sum, t1)
- sw t3, 0x08(dest)
- subu a2, a2, 0x10
- sw t4, 0x0c(dest)
- addu src, src, 0x10
- sw t0, 0x00(dest)
- srl t8, a2, 0x7
- addu dest, dest, 0x10
- sw t1, -0x0c(dest)
-
-begin_movement:
- beqz t8, 0f
- andi t2, a2, 0x40
-
-move_128bytes:
- CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
- CSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4)
- CSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4)
- subu t8, t8, 0x01
- addu src, src, 0x80
- bnez t8, move_128bytes
- addu dest, dest, 0x80
-
-0:
- beqz t2, 1f
- andi t2, a2, 0x20
-
-move_64bytes:
- CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
- addu src, src, 0x40
- addu dest, dest, 0x40
-
-1:
- beqz t2, do_end_words
- andi t8, a2, 0x1c
-
-move_32bytes:
- CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- andi t8, a2, 0x1c
- addu src, src, 0x20
- addu dest, dest, 0x20
-
-do_end_words:
- beqz t8, maybe_end_cruft
- srl t8, t8, 0x2
-
-end_words:
- EX(lw, t0, (src), l_fixup)
- subu t8, t8, 0x1
- ADDC(sum, t0)
- sw t0, (dest)
- addu src, src, 0x4
- bnez t8, end_words
- addu dest, dest, 0x4
-
-maybe_end_cruft:
- andi t2, a2, 0x3
-
-small_memcpy:
- j small_csumcpy; move a2, t2
- beqz t2, out
- move a2, t2
-
-end_bytes:
- EX(lb, t0, (src), l_fixup)
- subu a2, a2, 0x1
- sb t0, (dest)
- addu src, src, 0x1
- bnez a2, end_bytes
- addu dest, dest, 0x1
-
-out:
- jr ra
- move v0, sum
-
-/* ------------------------------------------------------------------------- */
-
-/* Bad, bad. At least try to align the source */
-
-memcpy_u_src:
- bnez t8, small_memcpy # < 8 bytes?
- move t2, a2
-
- beqz a2, out
- andi t7, src, 0x1 # odd alignment?
-
-u_hword_align:
- beqz t7, u_word_align
- andi t8, src, 0x2
-
- EX(lbu, t0, (src), l_fixup)
- subu a2, a2, 0x1
- sb t0, (dest)
-#ifdef __MIPSEL__
- sll t0, t0, 8
-#endif
- ADDC(sum, t0)
- addu src, src, 0x1
- addu dest, dest, 0x1
- andi t8, src, 0x2
-
-u_word_align:
- beqz t8, u_dword_align
- sltiu t8, a2, 56
-
- EX(lhu, t0, (src), l_fixup)
- subu a2, a2, 0x2
- ush t0, (dest)
- ADDC(sum, t0)
- sltiu t8, a2, 56
- addu dest, dest, 0x2
- addu src, src, 0x2
-
-u_dword_align:
- bnez t8, u_do_end_words
- move t8, a2
-
- andi t8, src, 0x4
- beqz t8, u_qword_align
- andi t8, src, 0x8
-
- EX(lw, t0, 0x00(src), l_fixup)
- subu a2, a2, 0x4
- ADDC(sum, t0)
- usw t0, 0x00(dest)
- addu src, src, 0x4
- addu dest, dest, 0x4
- andi t8, src, 0x8
-
-u_qword_align:
- beqz t8, u_oword_align
- andi t8, src, 0x10
-
- EX(lw, t0, 0x00(src), l_fixup)
- EX(lw, t1, 0x04(src), l_fixup)
- subu a2, a2, 0x8
- ADDC(sum, t0)
- ADDC(sum, t1)
- usw t0, 0x00(dest)
- addu src, src, 0x8
- usw t1, 0x04(dest)
- andi t8, src, 0x10
- addu dest, dest, 0x8
-
-u_oword_align:
- beqz t8, u_begin_movement
- srl t8, a2, 0x7
-
- EX(lw, t3, 0x08(src), l_fixup)
- EX(lw, t4, 0x0c(src), l_fixup)
- EX(lw, t0, 0x00(src), l_fixup)
- EX(lw, t1, 0x04(src), l_fixup)
- ADDC(sum, t3)
- ADDC(sum, t4)
- ADDC(sum, t0)
- ADDC(sum, t1)
- usw t3, 0x08(dest)
- subu a2, a2, 0x10
- usw t4, 0x0c(dest)
- addu src, src, 0x10
- usw t0, 0x00(dest)
- srl t8, a2, 0x7
- addu dest, dest, 0x10
- usw t1, -0x0c(dest)
-
-u_begin_movement:
- beqz t8, 0f
- andi t2, a2, 0x40
-
-u_move_128bytes:
- UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
- UCSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4)
- UCSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4)
- subu t8, t8, 0x01
- addu src, src, 0x80
- bnez t8, u_move_128bytes
- addu dest, dest, 0x80
-
-0:
- beqz t2, 1f
- andi t2, a2, 0x20
-
-u_move_64bytes:
- UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
- addu src, src, 0x40
- addu dest, dest, 0x40
-
-1:
- beqz t2, u_do_end_words
- andi t8, a2, 0x1c
-
-u_move_32bytes:
- UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
- andi t8, a2, 0x1c
- addu src, src, 0x20
- addu dest, dest, 0x20
-
-u_do_end_words:
- beqz t8, u_maybe_end_cruft
- srl t8, t8, 0x2
-
-u_end_words:
- EX(lw, t0, 0x00(src), l_fixup)
- subu t8, t8, 0x1
- ADDC(sum, t0)
- usw t0, 0x00(dest)
- addu src, src, 0x4
- bnez t8, u_end_words
- addu dest, dest, 0x4
-
-u_maybe_end_cruft:
- andi t2, a2, 0x3
-
-u_cannot_optimize:
- j small_csumcpy; move a2, t2
- beqz t2, out
- move a2, t2
-
-u_end_bytes:
- EX(lb, t0, (src), l_fixup)
- subu a2, a2, 0x1
- sb t0, (dest)
- addu src, src, 0x1
- bnez a2, u_end_bytes
- addu dest, dest, 0x1
-
- jr ra
- move v0, sum
- END(csum_partial_copy_from_user)
-
-l_fixup:
- beqz t7, 1f # odd buffer alignment?
- nop
- sll v1, sum, 8 # swap bytes
- srl sum, sum, 8
- or sum, v1
- andi sum, 0xffff
-1: ADDC(sum, a3) # Add csum argument.
-
- lw t0, THREAD_BUADDR($28) # clear the rest of the buffer
- nop
- subu t1, t0, src # where to start clearing
- addu a0, dest, t1
- move a1, zero # zero fill
- j __bzero
- subu a2, t5, t0 # a2 = bad - srcend bytes to go
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
new file mode 100644
index 000000000..ec731b800
--- /dev/null
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -0,0 +1,59 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $Id: csum_partial_copy.c,v 1.1 1996/07/03 14:03:47 ralf Exp $
+ */
+#include <net/checksum.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+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 real ...
+ * This is lots slower than the real thing (tm)
+ */
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+
+ return sum;
+}
+
+/*
+ * Copy from userspace and compute checksum. If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+ int len, unsigned int sum,
+ int *err_ptr)
+{
+ int *dst_err_ptr=NULL;
+ int missing;
+
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index 2bae5324d..907a471a6 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * $Id: memcpy.S,v 1.3 1998/04/27 06:00:36 ralf Exp $
+ * $Id: memcpy.S,v 1.2 1998/05/04 09:12:53 ralf Exp $
*
* Unified implementation of memcpy, memmove and the __copy_user backend.
* For __rmemcpy and memmove an exception is always a kernel bug, therefore
@@ -416,6 +416,7 @@ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
addu a0, a2 # dst = dst + len
addu a1, a2 # src = src + len
+#if 0 /* Horror fix */
xor t0, a0, a1
andi t0, t0, 0x3
move t7, a0
@@ -552,6 +553,7 @@ r_maybe_end_cruft:
r_small_memcpy:
beqz t2, r_out
move a2, t2
+#endif /* Horror fix */
r_end_bytes:
lb t0, -1(a1)
@@ -565,6 +567,7 @@ r_out:
jr ra
move a2, zero
+#if 0 /* Horror fix */
/* ------------------------------------------------------------------------- */
/* Bad, bad. At least try to align the source */
@@ -686,6 +689,7 @@ ru_end_bytes:
jr ra
move a2, zero
END(__rmemcpy)
+#endif /* Horror fix */
l_fixup: # clear the rest of the buffer
lw t0, THREAD_BUADDR($28)
diff --git a/arch/mips/sgi/kernel/indy_hpc.c b/arch/mips/sgi/kernel/indy_hpc.c
index eb00fe55c..eb62c3150 100644
--- a/arch/mips/sgi/kernel/indy_hpc.c
+++ b/arch/mips/sgi/kernel/indy_hpc.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: indy_hpc.c,v 1.2 1998/03/27 08:53:43 ralf Exp $
+ * $Id: indy_hpc.c,v 1.2 1998/04/05 11:23:57 ralf Exp $
*/
#include <linux/init.h>
@@ -20,27 +20,13 @@ 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;
+unsigned long sgi_hpc_write1, sgi_hpc_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;
-}
-
__initfunc(void sgihpc_init(void))
{
unsigned long sid, crev, brev;
@@ -96,12 +82,12 @@ __initfunc(void sgihpc_init(void))
prom_printf("\n");
#endif
- write1 = (HPC3_WRITE1_PRESET |
+ sgi_hpc_write1 = (HPC3_WRITE1_PRESET |
HPC3_WRITE1_KMRESET |
HPC3_WRITE1_ERESET |
HPC3_WRITE1_LC0OFF);
- write2 = (HPC3_WRITE2_EASEL |
+ sgi_hpc_write2 = (HPC3_WRITE2_EASEL |
HPC3_WRITE2_NTHRESH |
HPC3_WRITE2_TPSPEED |
HPC3_WRITE2_EPSEL |
@@ -109,9 +95,9 @@ __initfunc(void sgihpc_init(void))
HPC3_WRITE2_U1AMODE);
if(!sgi_guiness)
- write1 |= HPC3_WRITE1_GRESET;
- hpc3mregs->write1 = write1;
- hpc3mregs->write2 = write2;
+ sgi_hpc_write1 |= HPC3_WRITE1_GRESET;
+ hpc3mregs->write1 = sgi_hpc_write1;
+ hpc3mregs->write2 = sgi_hpc_write2;
hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW;
}
diff --git a/arch/mips/sgi/kernel/reset.c b/arch/mips/sgi/kernel/reset.c
index e465208cf..e6a58fa58 100644
--- a/arch/mips/sgi/kernel/reset.c
+++ b/arch/mips/sgi/kernel/reset.c
@@ -1,31 +1,200 @@
-/*
- * Reset a SGI.
+/* $Id: reset.c,v 1.6 1998/07/09 19:57:47 ralf Exp $
+ *
+ * Reset a SGI.
*
* 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, 1998 by Ralf Baechle
- *
- * $Id: reset.c,v 1.3 1998/03/26 07:31:16 ralf Exp $
*/
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/timer.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/system.h>
#include <asm/reboot.h>
#include <asm/sgialib.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+
+/*
+ * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds.
+ * I'm not shure if this feature is a good idea, for now it's here just to
+ * make the power button make behave just like under IRIX.
+ */
+#define POWERDOWN_TIMEOUT 120
+
+/*
+ * Blink frequency during reboot grace period and when paniced.
+ */
+#define POWERDOWN_FREQ (HZ / 4)
+#define PANIC_FREQ (HZ / 8)
+
+static struct timer_list power_timer, blink_timer, debounce_timer;
+static int shuting_down, has_paniced;
+
+static void sgi_machine_restart(char *command) __attribute__((noreturn));
+static void sgi_machine_halt(void) __attribute__((noreturn));
+static void sgi_machine_power_off(void) __attribute__((noreturn));
/* XXX How to pass the reboot command to the firmware??? */
-void sgi_machine_restart(char *command)
+static void sgi_machine_restart(char *command)
{
+ if (shuting_down)
+ sgi_machine_power_off();
prom_reboot();
}
-void sgi_machine_halt(void)
+static void sgi_machine_halt(void)
{
+ if (shuting_down)
+ sgi_machine_power_off();
prom_imode();
}
-void sgi_machine_power_off(void)
+static void sgi_machine_power_off(void)
+{
+ struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
+
+ cli();
+
+ clock->cmd |= 0x08; /* Disable watchdog */
+ clock->whsec = 0;
+ clock->wsec = 0;
+
+ while(1) {
+ hpc3mregs->panel=0xfe;
+ /* Good bye cruel world ... */
+
+ /* If we're still running, we probably got sent an alarm
+ interrupt. Read the flag to clear it. */
+ clock->halarm;
+ }
+}
+
+static void power_timeout(unsigned long data)
+{
+ sgi_machine_power_off();
+}
+
+static void blink_timeout(unsigned long data)
{
- prom_powerdown();
+ /* XXX fix this for fullhouse */
+ sgi_hpc_write1 ^= (HPC3_WRITE1_LC0OFF|HPC3_WRITE1_LC1OFF);
+ hpc3mregs->write1 = sgi_hpc_write1;
+
+ del_timer(&blink_timer);
+ blink_timer.expires = jiffies + data;
+ add_timer(&blink_timer);
+}
+
+static void debounce(unsigned long data)
+{
+ del_timer(&debounce_timer);
+ if (ioc_icontrol->istat1 & 2) { /* Interrupt still being sent. */
+ debounce_timer.expires = jiffies + 5; /* 0.05s */
+ add_timer(&debounce_timer);
+
+ hpc3mregs->panel = 0xf3;
+
+ return;
+ }
+
+ if (has_paniced)
+ prom_reboot();
+
+ enable_irq(9);
+}
+
+static inline void power_button(void)
+{
+ if (has_paniced)
+ return;
+
+ if (shuting_down || kill_proc(1, SIGINT, 1)) {
+ /* No init process or button pressed twice. */
+ sgi_machine_power_off();
+ }
+
+ shuting_down = 1;
+ blink_timer.data = POWERDOWN_FREQ;
+ blink_timeout(POWERDOWN_FREQ);
+
+ init_timer(&power_timer);
+ power_timer.function = power_timeout;
+ power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
+ add_timer(&power_timer);
+}
+
+static inline void volume_up_button(void)
+{
+ /* Later when we have sound support ... */
+}
+
+static inline void volume_down_button(void)
+{
+ /* Later when we have sound support ... */
+}
+
+static void panel_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int buttons;
+
+ buttons = hpc3mregs->panel;
+ hpc3mregs->panel = 3; /* power_interrupt | power_supply_on */
+
+ if (ioc_icontrol->istat1 & 2) { /* Wait until interrupt goes away */
+ disable_irq(9);
+ init_timer(&debounce_timer);
+ debounce_timer.function = debounce;
+ debounce_timer.expires = jiffies + 5;
+ add_timer(&debounce_timer);
+ }
+
+ if (!(buttons & 2)) /* Power button was pressed */
+ power_button();
+ if (!(buttons & 0x40)) /* Volume up button was pressed */
+ volume_up_button();
+ if (!(buttons & 0x10)) /* Volume down button was pressed */
+ volume_down_button();
+}
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ if (has_paniced)
+ return NOTIFY_DONE;
+ has_paniced = 1;
+
+ blink_timer.data = PANIC_FREQ;
+ blink_timeout(PANIC_FREQ);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ panic_event,
+ NULL,
+ 0
+};
+
+void indy_reboot_setup(void)
+{
+ static int setup_done;
+
+ if (setup_done)
+ return;
+ setup_done = 1;
+
+ _machine_restart = sgi_machine_restart;
+ _machine_halt = sgi_machine_halt;
+ _machine_power_off = sgi_machine_power_off;
+
+ request_irq(9, panel_int, 0, "Front Panel", NULL);
+ init_timer(&blink_timer);
+ blink_timer.function = blink_timeout;
+ notifier_chain_register(&panic_notifier_list, &panic_block);
}
diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c
index 9699f812c..451c785f2 100644
--- a/arch/mips/sgi/kernel/setup.c
+++ b/arch/mips/sgi/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.9 1998/05/07 02:57:21 ralf Exp $
+/* $Id: setup.c,v 1.10 1998/06/30 00:21:58 ralf Exp $
*
* setup.c: SGI specific setup, including init of the feature struct.
*
@@ -24,11 +24,8 @@
extern int serial_console; /* in console.c, of course */
-extern void sgi_machine_restart(char *command);
-extern void sgi_machine_halt(void);
-extern void sgi_machine_power_off(void);
-
extern struct rtc_ops indy_rtc_ops;
+void indy_reboot_setup(void);
static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64);
@@ -70,6 +67,13 @@ __initfunc(static void sgi_keyboard_setup(void))
kbd_write_output = sgi_write_output;
kbd_write_command = sgi_write_command;
kbd_read_status = sgi_read_status;
+
+ /* Dirty hack, this get's called as a callback from the keyboard
+ driver. We piggyback the initialization of the front panel
+ button handling on it even though they're technically not
+ related with the keyboard driver in any way. Doing it from
+ indy_setup wouldn't work since kmalloc isn't initialized yet. */
+ indy_reboot_setup();
}
__initfunc(static void sgi_irq_setup(void))
@@ -84,10 +88,6 @@ __initfunc(void sgi_setup(void))
irq_setup = sgi_irq_setup;
keyboard_setup = sgi_keyboard_setup;
- _machine_restart = sgi_machine_restart;
- _machine_halt = sgi_machine_halt;
- _machine_power_off = sgi_machine_power_off;
-
/* 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.
diff --git a/arch/mips/sgi/prom/misc.c b/arch/mips/sgi/prom/misc.c
index 8d7c300c7..d0072228c 100644
--- a/arch/mips/sgi/prom/misc.c
+++ b/arch/mips/sgi/prom/misc.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: misc.c,v 1.5 1998/03/27 08:53:47 ralf Exp $
+ * $Id: misc.c,v 1.3 1998/04/05 11:24:03 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -15,14 +15,12 @@
#include <asm/system.h>
extern unsigned long mips_cputype;
-extern int initialize_kbd(void);
extern void *sgiwd93_host;
extern void reset_wd33c93(void *instance);
void prom_halt(void)
{
bcops->bc_disable();
- initialize_kbd();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
@@ -33,7 +31,6 @@ void prom_halt(void)
void prom_powerdown(void)
{
bcops->bc_disable();
- initialize_kbd();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
@@ -45,7 +42,6 @@ void prom_powerdown(void)
void prom_restart(void)
{
bcops->bc_disable();
- initialize_kbd();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
@@ -56,7 +52,6 @@ void prom_restart(void)
void prom_reboot(void)
{
bcops->bc_disable();
- initialize_kbd();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
@@ -67,7 +62,6 @@ void prom_reboot(void)
void prom_imode(void)
{
bcops->bc_disable();
- initialize_kbd();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);