From cf00b9f677c32c4f0ad187bed33e7bf2209db3b8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 10 Jul 1998 01:14:47 +0000 Subject: o Support for the front panel on the Indy. The panel work now as a user would expect it to work, like under IRIX with the exception that the machine doesn't freeze solid as long as the button is pressed. o Realtime clock driver (CONFIG_SGI_DS1286) for the Indy. Includes /proc/rtc interface which tells you everything about your RTC which you never wanted to know. You have to configure this driver into your kernel or you won't be able to set your RTC. o Some cleanup of the RTC interfaces in Linux, RTC does no longer mean PC-style RTC. The userland interface definitions are now in . We still need some more cleanup until we can enable several RTC drivers. o Virtual aliasing fixes for ptrace(2). o Add ptrace(2) interface definitions needed to build GDB to . o Revert to some older routines, the newer optimized ones are buggy. o On panic the Indy LED will be blinking fast crying to the admin passing by [music from Rocky Horror show] ``fix me, fix me, fix me''. o On panic the power button will only reboot the machine, not power it down. That's probably more what people want it to do. o Remove some old files. o Did I tell you that CVS is buggy? --- arch/mips/kernel/ptrace.c | 5 +- arch/mips/kernel/signal.c | 8 +- arch/mips/kernel/traps.c | 47 +--- arch/mips/lib/csum_partial_copy.S | 519 -------------------------------------- arch/mips/lib/csum_partial_copy.c | 59 +++++ arch/mips/lib/memcpy.S | 6 +- arch/mips/sgi/kernel/indy_hpc.c | 28 +- arch/mips/sgi/kernel/reset.c | 185 +++++++++++++- arch/mips/sgi/kernel/setup.c | 18 +- arch/mips/sgi/prom/misc.c | 8 +- 10 files changed, 280 insertions(+), 603 deletions(-) delete mode 100644 arch/mips/lib/csum_partial_copy.S create mode 100644 arch/mips/lib/csum_partial_copy.c (limited to 'arch') 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 #include -#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 -#include -#include - -/* - * 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, + * 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 +#include +#include +#include +#include + +/* + * 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 @@ -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 +#include +#include +#include #include +#include #include #include #include +#include +#include + +/* + * 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 #include @@ -15,14 +15,12 @@ #include 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); -- cgit v1.2.3