diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 8 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 47 | ||||
-rw-r--r-- | arch/mips/lib/csum_partial_copy.S | 519 | ||||
-rw-r--r-- | arch/mips/lib/csum_partial_copy.c | 59 | ||||
-rw-r--r-- | arch/mips/lib/memcpy.S | 6 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/indy_hpc.c | 28 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/reset.c | 185 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/setup.c | 18 | ||||
-rw-r--r-- | arch/mips/sgi/prom/misc.c | 8 |
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(¤t->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(¤t->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); |