summaryrefslogtreecommitdiff
path: root/release/src/linux/linux/arch/mips/lib
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
commit008d0be72b2f160382c6e880765e96b64a050c65 (patch)
tree36f48a98a3815a408e2ce1693dd182af90f80305 /release/src/linux/linux/arch/mips/lib
parent611becfb8726c60cb060368541ad98191d4532f5 (diff)
downloadtomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.gz
tomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.bz2
imported original firmware WRT54GL_v4.30.11_11_US
Diffstat (limited to 'release/src/linux/linux/arch/mips/lib')
-rw-r--r--release/src/linux/linux/arch/mips/lib/Makefile26
-rw-r--r--release/src/linux/linux/arch/mips/lib/csum_partial.S240
-rw-r--r--release/src/linux/linux/arch/mips/lib/csum_partial_copy.c56
-rw-r--r--release/src/linux/linux/arch/mips/lib/dump_tlb.c231
-rw-r--r--release/src/linux/linux/arch/mips/lib/floppy-no.c57
-rw-r--r--release/src/linux/linux/arch/mips/lib/floppy-std.c150
-rw-r--r--release/src/linux/linux/arch/mips/lib/ide-no.c70
-rw-r--r--release/src/linux/linux/arch/mips/lib/ide-std.c137
-rw-r--r--release/src/linux/linux/arch/mips/lib/kbd-no.c62
-rw-r--r--release/src/linux/linux/arch/mips/lib/kbd-std.c85
-rw-r--r--release/src/linux/linux/arch/mips/lib/mcount.S56
-rw-r--r--release/src/linux/linux/arch/mips/lib/memcpy.S503
-rw-r--r--release/src/linux/linux/arch/mips/lib/memset.S141
-rw-r--r--release/src/linux/linux/arch/mips/lib/promlib.c24
-rw-r--r--release/src/linux/linux/arch/mips/lib/r3k_dump_tlb.c187
-rw-r--r--release/src/linux/linux/arch/mips/lib/rtc-no.c30
-rw-r--r--release/src/linux/linux/arch/mips/lib/rtc-std.c34
-rw-r--r--release/src/linux/linux/arch/mips/lib/strlen_user.S40
-rw-r--r--release/src/linux/linux/arch/mips/lib/strncpy_user.S58
-rw-r--r--release/src/linux/linux/arch/mips/lib/strnlen_user.S49
-rw-r--r--release/src/linux/linux/arch/mips/lib/tinycon.c119
-rw-r--r--release/src/linux/linux/arch/mips/lib/watch.S60
22 files changed, 2415 insertions, 0 deletions
diff --git a/release/src/linux/linux/arch/mips/lib/Makefile b/release/src/linux/linux/arch/mips/lib/Makefile
new file mode 100644
index 00000000..64ba1f56
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for MIPS-specific library files..
+#
+
+USE_STANDARD_AS_RULE := true
+
+L_TARGET = lib.a
+
+obj-y += csum_partial.o csum_partial_copy.o \
+ promlib.o rtc-std.o rtc-no.o memcpy.o \
+ memset.o watch.o strlen_user.o \
+ strncpy_user.o strnlen_user.o
+
+ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y)
+ obj-y += r3k_dump_tlb.o
+else
+ obj-y += dump_tlb.o
+endif
+
+obj-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o
+obj-$(subst m,y,$(CONFIG_IDE)) += ide-std.o ide-no.o # needed for ide module
+obj-$(CONFIG_PC_KEYB) += kbd-std.o kbd-no.o
+
+obj-$(CONFIG_MCOUNT) += mcount.o
+
+include $(TOPDIR)/Rules.make
diff --git a/release/src/linux/linux/arch/mips/lib/csum_partial.S b/release/src/linux/linux/arch/mips/lib/csum_partial.S
new file mode 100644
index 00000000..ef83e776
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/csum_partial.S
@@ -0,0 +1,240 @@
+/*
+ * 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/regdef.h>
+
+#define ADDC(sum,reg) \
+ addu sum, reg; \
+ sltu v1, sum, reg; \
+ addu sum, v1
+
+#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
+ lw t0, (offset + 0x00)(src); \
+ lw t1, (offset + 0x04)(src); \
+ lw t2, (offset + 0x08)(src); \
+ lw t3, (offset + 0x0c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+ lw t0, (offset + 0x10)(src); \
+ lw t1, (offset + 0x14)(src); \
+ lw t2, (offset + 0x18)(src); \
+ lw t3, (offset + 0x1c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+
+/*
+ * a0: source address
+ * a1: length of the area to checksum
+ * a2: partial checksum
+ */
+
+#define src a0
+#define dest a1
+#define sum v0
+
+ .text
+ .set noreorder
+
+/* unknown src alignment and < 8 bytes to go */
+small_csumcpy:
+ move a1, t2
+
+ andi t0, a1, 4
+ beqz t0, 1f
+ andi t0, a1, 2
+
+ /* Still a full word to go */
+ ulw t1, (src)
+ addiu src, 4
+ ADDC(sum, t1)
+
+1: move t1, zero
+ beqz t0, 1f
+ andi t0, a1, 1
+
+ /* Still a halfword to go */
+ ulhu t1, (src)
+ addiu src, 2
+
+1: beqz t0, 1f
+ sll t1, t1, 16
+
+ lbu t2, (src)
+ nop
+
+#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, a2)
+ jr ra
+ .set noreorder
+
+/* ------------------------------------------------------------------------- */
+
+ .align 5
+LEAF(csum_partial)
+ move sum, zero
+ move t7, zero
+
+ sltiu t8, a1, 0x8
+ bnez t8, small_csumcpy /* < 8 bytes to copy */
+ move t2, a1
+
+ beqz a1, out
+ andi t7, src, 0x1 /* odd buffer? */
+
+hword_align:
+ beqz t7, word_align
+ andi t8, src, 0x2
+
+ lbu t0, (src)
+ subu a1, a1, 0x1
+#ifdef __MIPSEL__
+ sll t0, t0, 8
+#endif
+ ADDC(sum, t0)
+ addu src, src, 0x1
+ andi t8, src, 0x2
+
+word_align:
+ beqz t8, dword_align
+ sltiu t8, a1, 56
+
+ lhu t0, (src)
+ subu a1, a1, 0x2
+ ADDC(sum, t0)
+ sltiu t8, a1, 56
+ addu src, src, 0x2
+
+dword_align:
+ bnez t8, do_end_words
+ move t8, a1
+
+ andi t8, src, 0x4
+ beqz t8, qword_align
+ andi t8, src, 0x8
+
+ lw t0, 0x00(src)
+ subu a1, a1, 0x4
+ ADDC(sum, t0)
+ addu src, src, 0x4
+ andi t8, src, 0x8
+
+qword_align:
+ beqz t8, oword_align
+ andi t8, src, 0x10
+
+ lw t0, 0x00(src)
+ lw t1, 0x04(src)
+ subu a1, a1, 0x8
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+ addu src, src, 0x8
+ andi t8, src, 0x10
+
+oword_align:
+ beqz t8, begin_movement
+ srl t8, a1, 0x7
+
+ lw t3, 0x08(src)
+ lw t4, 0x0c(src)
+ lw t0, 0x00(src)
+ lw t1, 0x04(src)
+ ADDC(sum, t3)
+ ADDC(sum, t4)
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+ subu a1, a1, 0x10
+ addu src, src, 0x10
+ srl t8, a1, 0x7
+
+begin_movement:
+ beqz t8, 1f
+ andi t2, a1, 0x40
+
+move_128bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
+ subu t8, t8, 0x01
+ bnez t8, move_128bytes
+ addu src, src, 0x80
+
+1:
+ beqz t2, 1f
+ andi t2, a1, 0x20
+
+move_64bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+ addu src, src, 0x40
+
+1:
+ beqz t2, do_end_words
+ andi t8, a1, 0x1c
+
+move_32bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ andi t8, a1, 0x1c
+ addu src, src, 0x20
+
+do_end_words:
+ beqz t8, maybe_end_cruft
+ srl t8, t8, 0x2
+
+end_words:
+ lw t0, (src)
+ subu t8, t8, 0x1
+ ADDC(sum, t0)
+ bnez t8, end_words
+ addu src, src, 0x4
+
+maybe_end_cruft:
+ andi t2, a1, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a1, t2
+ beqz t2, out
+ move a1, t2
+
+end_bytes:
+ lb t0, (src)
+ subu a1, a1, 0x1
+ bnez a2, end_bytes
+ addu src, src, 0x1
+
+out:
+ jr ra
+ move v0, sum
+ END(csum_partial)
diff --git a/release/src/linux/linux/arch/mips/lib/csum_partial_copy.c b/release/src/linux/linux/arch/mips/lib/csum_partial_copy.c
new file mode 100644
index 00000000..7348cf23
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/csum_partial_copy.c
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+#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 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/release/src/linux/linux/arch/mips/lib/dump_tlb.c b/release/src/linux/linux/arch/mips/lib/dump_tlb.c
new file mode 100644
index 00000000..a3c4cc13
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/dump_tlb.c
@@ -0,0 +1,231 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/cachectl.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+static inline const char *msg2str(unsigned int mask)
+{
+ switch (mask) {
+ case PM_4K: return "4kb";
+ case PM_16K: return "16kb";
+ case PM_64K: return "64kb";
+ case PM_256K: return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+ case PM_1M: return "1Mb";
+ case PM_4M: return "4Mb";
+ case PM_16M: return "16Mb";
+ case PM_64M: return "64Mb";
+ case PM_256M: return "256Mb";
+#endif
+ }
+}
+
+void dump_tlb(int first, int last)
+{
+ int i;
+ unsigned int pagemask, c0, c1, asid;
+ unsigned long long entrylo0, entrylo1;
+ unsigned long entryhi;
+
+ asid = read_c0_entryhi() & 0xff;
+
+ printk("\n");
+ for(i=first;i<=last;i++) {
+ write_c0_index(i);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoreorder\n\t"
+ "nop;nop;nop;nop\n\t"
+ "tlbr\n\t"
+ "nop;nop;nop;nop\n\t"
+ ".set\treorder\n\t"
+ ".set\tmips0\n\t");
+ pagemask = read_c0_pagemask();
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+ entrylo1 = read_c0_entrylo1();
+
+ /* Unused entries have a virtual address in KSEG0. */
+ if ((entryhi & 0xf0000000) != 0x80000000
+ && (entryhi & 0xff) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msg2str(pagemask));
+
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("va=%08lx asid=%02lx\n",
+ (entryhi & 0xffffe000), (entryhi & 0xff));
+ printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
+ (entrylo0 << 6) & PAGE_MASK, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1));
+ printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
+ (entrylo1 << 6) & PAGE_MASK, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1));
+ printk("\n");
+ }
+ }
+
+ write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, mips_cpu.tlbsize - 1);
+}
+
+void dump_tlb_wired(void)
+{
+ int wired;
+
+ wired = read_c0_wired();
+ printk("Wired: %d", wired);
+ dump_tlb(0, read_c0_wired());
+}
+
+#define BARRIER \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+void
+dump_tlb_addr(unsigned long addr)
+{
+ unsigned int flags, oldpid;
+ int index;
+
+ __save_and_cli(flags);
+ oldpid = read_c0_entryhi() & 0xff;
+ BARRIER;
+ write_c0_entryhi((addr & PAGE_MASK) | oldpid);
+ BARRIER;
+ tlb_probe();
+ BARRIER;
+ index = read_c0_index();
+ write_c0_entryhi(oldpid);
+ __restore_flags(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
+void
+dump_tlb_nonwired(void)
+{
+ dump_tlb(read_c0_wired(), mips_cpu.tlbsize - 1);
+}
+
+void
+dump_list_process(struct task_struct *t, void *address)
+{
+ pgd_t *page_dir, *pgd;
+ pmd_t *pmd;
+ pte_t *pte, page;
+ unsigned int addr;
+ unsigned long val;
+
+ addr = (unsigned int) address;
+
+ printk("Addr == %08x\n", addr);
+ printk("task == %08p\n", t);
+ printk("task->mm == %08p\n", t->mm);
+ //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
+
+ if (addr > KSEG0)
+ page_dir = pgd_offset_k(0);
+ else
+ page_dir = pgd_offset(t->mm, 0);
+ printk("page_dir == %08x\n", (unsigned int) page_dir);
+
+ if (addr > KSEG0)
+ pgd = pgd_offset_k(addr);
+ else
+ pgd = pgd_offset(t->mm, addr);
+ printk("pgd == %08x, ", (unsigned int) pgd);
+
+ pmd = pmd_offset(pgd, addr);
+ printk("pmd == %08x, ", (unsigned int) pmd);
+
+ pte = pte_offset(pmd, addr);
+ printk("pte == %08x, ", (unsigned int) pte);
+
+ page = *pte;
+#ifdef CONFIG_64BIT_PHYS_ADDR
+ printk("page == %08Lx\n", pte_val(page));
+#else
+ printk("page == %08lx\n", pte_val(page));
+#endif
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_R4KBUG) printk("r4kbug ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
+}
+
+void
+dump_list_current(void *address)
+{
+ dump_list_process(current, address);
+}
+
+unsigned int
+vtop(void *address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned int addr, paddr;
+
+ addr = (unsigned long) address;
+ pgd = pgd_offset(current->mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+ paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+ paddr |= (addr & ~PAGE_MASK);
+
+ return paddr;
+}
+
+void
+dump16(unsigned long *p)
+{
+ int i;
+
+ for(i=0;i<8;i++)
+ {
+ printk("*%8p = %08lx, ", p, *p); p++;
+ printk("*%8p = %08lx\n", p, *p); p++;
+ }
+}
diff --git a/release/src/linux/linux/arch/mips/lib/floppy-no.c b/release/src/linux/linux/arch/mips/lib/floppy-no.c
new file mode 100644
index 00000000..b87110e8
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/floppy-no.c
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * Dummy file for machines without standard floppy drives.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/floppy.h>
+
+/*
+ * How to access the FDC's registers.
+ */
+static void no_fd_dummy(void)
+{
+ panic("no_fd_dummy called - shouldn't happen");
+}
+
+static unsigned long no_fd_getfdaddr1(void)
+{
+ return (unsigned long)-1; /* No FDC nowhere ... */
+}
+
+static unsigned long no_fd_drive_type(unsigned long n)
+{
+ return 0;
+}
+
+struct fd_ops no_fd_ops = {
+ /*
+ * How to access the floppy controller's ports
+ */
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ /*
+ * How to access the floppy DMA functions.
+ */
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ no_fd_getfdaddr1,
+ (void *) no_fd_dummy,
+ (void *) no_fd_dummy,
+ no_fd_drive_type
+};
diff --git a/release/src/linux/linux/arch/mips/lib/floppy-std.c b/release/src/linux/linux/arch/mips/lib/floppy-std.c
new file mode 100644
index 00000000..8560138c
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/floppy-std.c
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ *
+ * Access the floppy hardware on PC style hardware
+ *
+ * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/floppy.h>
+#include <asm/keyboard.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mc146818rtc.h>
+#include <asm/pgtable.h>
+
+/*
+ * How to access the FDC's registers.
+ */
+static unsigned char std_fd_inb(unsigned int port)
+{
+ return inb_p(port);
+}
+
+static void std_fd_outb(unsigned char value, unsigned int port)
+{
+ outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static void std_fd_enable_dma(int channel)
+{
+ enable_dma(channel);
+}
+
+static void std_fd_disable_dma(int channel)
+{
+ disable_dma(channel);
+}
+
+static int std_fd_request_dma(int channel)
+{
+ return request_dma(channel, "floppy");
+}
+
+static void std_fd_free_dma(int channel)
+{
+ free_dma(channel);
+}
+
+static void std_fd_clear_dma_ff(int channel)
+{
+ clear_dma_ff(channel);
+}
+
+static void std_fd_set_dma_mode(int channel, char mode)
+{
+ set_dma_mode(channel, mode);
+}
+
+static void std_fd_set_dma_addr(int channel, unsigned int addr)
+{
+ set_dma_addr(channel, addr);
+}
+
+static void std_fd_set_dma_count(int channel, unsigned int count)
+{
+ set_dma_count(channel, count);
+}
+
+static int std_fd_get_dma_residue(int channel)
+{
+ return get_dma_residue(channel);
+}
+
+static void std_fd_enable_irq(int irq)
+{
+ enable_irq(irq);
+}
+
+static void std_fd_disable_irq(int irq)
+{
+ disable_irq(irq);
+}
+
+static unsigned long std_fd_getfdaddr1(void)
+{
+ return 0x3f0;
+}
+
+static unsigned long std_fd_dma_mem_alloc(unsigned long size)
+{
+ unsigned long mem;
+
+ mem = __get_dma_pages(GFP_KERNEL,get_order(size));
+
+ return mem;
+}
+
+static void std_fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+ free_pages(addr, get_order(size));
+}
+
+static unsigned long std_fd_drive_type(unsigned long n)
+{
+ if (n == 0)
+ return 4; /* 3,5", 1.44mb */
+
+ return 0;
+}
+
+struct fd_ops std_fd_ops = {
+ /*
+ * How to access the floppy controller's ports
+ */
+ std_fd_inb,
+ std_fd_outb,
+ /*
+ * How to access the floppy DMA functions.
+ */
+ std_fd_enable_dma,
+ std_fd_disable_dma,
+ std_fd_request_dma,
+ std_fd_free_dma,
+ std_fd_clear_dma_ff,
+ std_fd_set_dma_mode,
+ std_fd_set_dma_addr,
+ std_fd_set_dma_count,
+ std_fd_get_dma_residue,
+ std_fd_enable_irq,
+ std_fd_disable_irq,
+ std_fd_getfdaddr1,
+ std_fd_dma_mem_alloc,
+ std_fd_dma_mem_free,
+ std_fd_drive_type
+};
diff --git a/release/src/linux/linux/arch/mips/lib/ide-no.c b/release/src/linux/linux/arch/mips/lib/ide-no.c
new file mode 100644
index 00000000..0d78feb2
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/ide-no.c
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * Stub IDE routines to keep Linux from crashing on machine which don't
+ * have IDE like the Indy.
+ *
+ * Copyright (C) 1998, 1999 by Ralf Baechle
+ */
+#include <linux/hdreg.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <asm/hdreg.h>
+#include <asm/ptrace.h>
+
+static int no_ide_default_irq(ide_ioreg_t base)
+{
+ return 0;
+}
+
+static ide_ioreg_t no_ide_default_io_base(int index)
+{
+ return 0;
+}
+
+static void no_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+}
+
+static int no_ide_request_irq(unsigned int irq,
+ void (*handler)(int,void *, struct pt_regs *),
+ unsigned long flags, const char *device,
+ void *dev_id)
+{
+ panic("no_no_ide_request_irq called - shouldn't happen");
+}
+
+static void no_ide_free_irq(unsigned int irq, void *dev_id)
+{
+ panic("no_ide_free_irq called - shouldn't happen");
+}
+
+static int no_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ panic("no_ide_check_region called - shouldn't happen");
+}
+
+static void no_ide_request_region(ide_ioreg_t from, unsigned int extent,
+ const char *name)
+{
+ panic("no_ide_request_region called - shouldn't happen");
+}
+
+static void no_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+ panic("no_ide_release_region called - shouldn't happen");
+}
+
+struct ide_ops no_ide_ops = {
+ &no_ide_default_irq,
+ &no_ide_default_io_base,
+ &no_ide_init_hwif_ports,
+ &no_ide_request_irq,
+ &no_ide_free_irq,
+ &no_ide_check_region,
+ &no_ide_request_region,
+ &no_ide_release_region
+};
diff --git a/release/src/linux/linux/arch/mips/lib/ide-std.c b/release/src/linux/linux/arch/mips/lib/ide-std.c
new file mode 100644
index 00000000..dd96e3e5
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/ide-std.c
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ *
+ * IDE routines for typical pc-like standard configurations.
+ *
+ * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <asm/ptrace.h>
+#include <asm/hdreg.h>
+#include <asm/io.h>
+#include <asm/paccess.h>
+
+static int std_ide_default_irq(ide_ioreg_t base)
+{
+ switch (base) {
+ case 0x1f0: return 14;
+ case 0x170: return 15;
+ case 0x1e8: return 11;
+ case 0x168: return 10;
+ case 0x1e0: return 8;
+ case 0x160: return 12;
+ default:
+ return 0;
+ }
+}
+
+static ide_ioreg_t std_ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ case 4: return 0x1e0;
+ case 5: return 0x160;
+ default:
+ return 0;
+ }
+}
+
+static void std_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+ ide_ioreg_t reg = data_port;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += 1;
+ }
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+ }
+ if (irq != NULL)
+ *irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
+}
+
+static int std_ide_request_irq(unsigned int irq,
+ void (*handler)(int,void *, struct pt_regs *),
+ unsigned long flags, const char *device,
+ void *dev_id)
+{
+ return request_irq(irq, handler, flags, device, dev_id);
+}
+
+static void std_ide_free_irq(unsigned int irq, void *dev_id)
+{
+ free_irq(irq, dev_id);
+}
+
+static int std_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ int ret;
+
+ if ((ret = check_region(from, extent)))
+ return ret;
+
+ /* Standard IDE ports may not be accessible */
+ switch (extent) {
+ case 1: {
+ u8 val;
+ ret = get_dbe(val, (u8 *)(mips_io_port_base + (unsigned long) from));
+ break;
+ }
+ case 2: {
+ u16 val;
+ ret = get_dbe(val, (u16 *)(mips_io_port_base + (unsigned long) from));
+ break;
+ }
+ case 4: {
+ u32 val;
+ ret = get_dbe(val, (u32 *)(mips_io_port_base + (unsigned long) from));
+ break;
+ }
+ case 8: {
+ u64 val;
+ ret = get_dbe(val, (u64 *)(mips_io_port_base + (unsigned long) from));
+ break;
+ }
+ default:
+ ret = -EFAULT;
+ break;
+ }
+
+ return ret;
+}
+
+static void std_ide_request_region(ide_ioreg_t from, unsigned int extent,
+ const char *name)
+{
+ request_region(from, extent, name);
+}
+
+static void std_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+ release_region(from, extent);
+}
+
+struct ide_ops std_ide_ops = {
+ &std_ide_default_irq,
+ &std_ide_default_io_base,
+ &std_ide_init_hwif_ports,
+ &std_ide_request_irq,
+ &std_ide_free_irq,
+ &std_ide_check_region,
+ &std_ide_request_region,
+ &std_ide_release_region
+};
diff --git a/release/src/linux/linux/arch/mips/lib/kbd-no.c b/release/src/linux/linux/arch/mips/lib/kbd-no.c
new file mode 100644
index 00000000..dcf3d0c4
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/kbd-no.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ * Stub keyboard and psaux routines to keep Linux from crashing on machines
+ * without a keyboard.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <asm/keyboard.h>
+
+static void no_kbd_request_region(void)
+{
+ /* No I/O ports are being used on the Indy. */
+}
+
+static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+ return -ENODEV;
+}
+
+static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+ return -ENODEV;
+}
+
+static void no_aux_free_irq(void)
+{
+}
+
+static unsigned char no_kbd_read_input(void)
+{
+ return 0;
+}
+
+static void no_kbd_write_output(unsigned char val)
+{
+}
+
+static void no_kbd_write_command(unsigned char val)
+{
+}
+
+static unsigned char no_kbd_read_status(void)
+{
+ return 0;
+}
+
+struct kbd_ops no_kbd_ops = {
+ no_kbd_request_region,
+ no_kbd_request_irq,
+
+ no_aux_request_irq,
+ no_aux_free_irq,
+
+ no_kbd_read_input,
+ no_kbd_write_output,
+ no_kbd_write_command,
+ no_kbd_read_status
+};
diff --git a/release/src/linux/linux/arch/mips/lib/kbd-std.c b/release/src/linux/linux/arch/mips/lib/kbd-std.c
new file mode 100644
index 00000000..e1cba545
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/kbd-std.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ * Routines for standard PC style keyboards accessible via I/O ports.
+ *
+ * Copyright (C) 1998, 1999 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/pc_keyb.h>
+#include <asm/keyboard.h>
+#include <asm/io.h>
+
+#define KEYBOARD_IRQ 1
+#define AUX_IRQ 12
+
+static void std_kbd_request_region(void)
+{
+#ifdef CONFIG_MIPS_ITE8172
+ request_region(0x14000060, 16, "keyboard");
+#else
+ request_region(0x60, 16, "keyboard");
+#endif
+}
+
+static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+ return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
+}
+
+static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+ return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL);
+}
+
+static void std_aux_free_irq(void)
+{
+ free_irq(AUX_IRQ, NULL);
+}
+
+static unsigned char std_kbd_read_input(void)
+{
+ return inb(KBD_DATA_REG);
+}
+
+static void std_kbd_write_output(unsigned char val)
+{
+ int status;
+
+ do {
+ status = inb(KBD_CNTL_REG);
+ } while (status & KBD_STAT_IBF);
+ outb(val, KBD_DATA_REG);
+}
+
+static void std_kbd_write_command(unsigned char val)
+{
+ int status;
+
+ do {
+ status = inb(KBD_CNTL_REG);
+ } while (status & KBD_STAT_IBF);
+ outb(val, KBD_CNTL_REG);
+}
+
+static unsigned char std_kbd_read_status(void)
+{
+ return inb(KBD_STATUS_REG);
+}
+
+struct kbd_ops std_kbd_ops = {
+ std_kbd_request_region,
+ std_kbd_request_irq,
+
+ std_aux_request_irq,
+ std_aux_free_irq,
+
+ std_kbd_read_input,
+ std_kbd_write_output,
+ std_kbd_write_command,
+ std_kbd_read_status
+};
diff --git a/release/src/linux/linux/arch/mips/lib/mcount.S b/release/src/linux/linux/arch/mips/lib/mcount.S
new file mode 100644
index 00000000..5dcddfff
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/mcount.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ *
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ *
+ * This file implements mcount(), which is used to collect profiling data.
+ * We provide several variants to accomodate different types of callers at
+ * the lowest possible overhead.
+ */
+
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <linux/config.h>
+
+.macro MCOUNT
+ .set push
+ .set noat
+ .set noreorder
+#if defined(CONFIG_KERNPROF) || defined(CONFIG_KERNPROF_MODULE)
+ lw t9, (mcount_hook)
+ beqz t9, 1f
+ nop
+ subu sp, 16
+ sw a0, 0(sp)
+ sw a1, 4(sp)
+ sw a2, 8(sp)
+ sw a3, 12(sp)
+ sw ra, 16(sp)
+ sw AT, 20(sp)
+ move a1, ra # mcount's parent (another gas bug -> ')
+ jalr t9
+ move a0, AT # mcount's parent's parent
+ lw ra, 20(sp)
+ lw AT, 16(sp)
+ lw a3, 12(sp)
+ lw a2, 8(sp)
+ lw a1, 4(sp)
+ lw a0, 0(sp)
+ jr AT
+ addu sp, 24
+#endif
+1: move t0, AT
+ move AT, ra
+ move ra, t0
+ jr AT
+ addu sp, 8 # sp is adjusted by -8 when we are called
+ .set pop
+.endm
+
+
+/*
+ * This is the main variant and is called by C code. GCC's -pg option
+ * automatically instruments every C function with a call to this.
+ */
+FEXPORT(_mcount)
+ MCOUNT
diff --git a/release/src/linux/linux/arch/mips/lib/memcpy.S b/release/src/linux/linux/arch/mips/lib/memcpy.S
new file mode 100644
index 00000000..de093a94
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/memcpy.S
@@ -0,0 +1,503 @@
+/*
+ * 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.
+ *
+ * Unified implementation of memcpy, memmove and the __copy_user backend.
+ *
+ * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
+ * Copyright (C) 2002 Broadcom, Inc.
+ * memcpy/copy_user author: Mark Vandevoorde
+ *
+ * Mnemonic names for arguments to memcpy/__copy_user
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define dst a0
+#define src a1
+#define len a2
+
+/*
+ * Spec
+ *
+ * memcpy copies len bytes from src to dst and sets v0 to dst.
+ * It assumes that
+ * - src and dst don't overlap
+ * - src is readable
+ * - dst is writable
+ * memcpy uses the standard calling convention
+ *
+ * __copy_user copies up to len bytes from src to dst and sets a2 (len) to
+ * the number of uncopied bytes due to an exception caused by a read or write.
+ * __copy_user assumes that src and dst don't overlap, and that the call is
+ * implementing one of the following:
+ * copy_to_user
+ * - src is readable (no exceptions when reading src)
+ * copy_from_user
+ * - dst is writable (no exceptions when writing dst)
+ * __copy_user uses a non-standard calling convention; see
+ * include/asm-mips/uaccess.h
+ *
+ * When an exception happens on a load, the handler must
+ # ensure that all of the destination buffer is overwritten to prevent
+ * leaking information to user mode programs.
+ */
+
+/*
+ * Implementation
+ */
+
+/*
+ * The exception handler for loads requires that:
+ * 1- AT contain the address of the byte just past the end of the source
+ * of the copy,
+ * 2- src_entry <= src < AT, and
+ * 3- (dst - src) == (dst_entry - src_entry),
+ * The _entry suffix denotes values when __copy_user was called.
+ *
+ * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
+ * (2) is met by incrementing src by the number of bytes copied
+ * (3) is met by not doing loads between a pair of increments of dst and src
+ *
+ * The exception handlers for stores adjust len (if necessary) and return.
+ * These handlers do not need to overwrite any data.
+ *
+ * For __rmemcpy and memmove an exception is always a kernel bug, therefore
+ * they're not protected.
+ */
+
+#define EXC(inst_reg,addr,handler) \
+9: inst_reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Only on the 64-bit kernel we can made use of 64-bit registers.
+ */
+#ifdef CONFIG_MIPS64
+#define USE_DOUBLE
+#endif
+
+#ifdef USE_DOUBLE
+
+#define LOAD ld
+#define LOADL ldl
+#define LOADR ldr
+#define STOREL sdl
+#define STORER sdr
+#define STORE sd
+#define ADD daddu
+#define SUB dsubu
+#define SRL dsrl
+#define SRA dsra
+#define SLL dsll
+#define SLLV dsllv
+#define SRLV dsrlv
+#define NBYTES 8
+#define LOG_NBYTES 3
+
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+
+#else
+
+#define LOAD lw
+#define LOADL lwl
+#define LOADR lwr
+#define STOREL swl
+#define STORER swr
+#define STORE sw
+#define ADD addu
+#define SUB subu
+#define SRL srl
+#define SLL sll
+#define SRA sra
+#define SLLV sllv
+#define SRLV srlv
+#define NBYTES 4
+#define LOG_NBYTES 2
+
+#endif /* USE_DOUBLE */
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LDFIRST LOADR
+#define LDREST LOADL
+#define STFIRST STORER
+#define STREST STOREL
+#define SHIFT_DISCARD SLLV
+#else
+#define LDFIRST LOADL
+#define LDREST LOADR
+#define STFIRST STOREL
+#define STREST STORER
+#define SHIFT_DISCARD SRLV
+#endif
+
+#define FIRST(unit) ((unit)*NBYTES)
+#define REST(unit) (FIRST(unit)+NBYTES-1)
+#define UNIT(unit) FIRST(unit)
+
+#define ADDRMASK (NBYTES-1)
+
+ .text
+ .set noreorder
+ .set noat
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+ .align 5
+LEAF(memcpy) /* a0=dst a1=src a2=len */
+ move v0, dst /* return value */
+__memcpy:
+FEXPORT(__copy_user)
+ /*
+ * Note: dst & src may be unaligned, len may be 0
+ * Temps
+ */
+#define rem t8
+
+ /*
+ * The "issue break"s below are very approximate.
+ * Issue delays for dcache fills will perturb the schedule, as will
+ * load queue full replay traps, etc.
+ *
+ * If len < NBYTES use byte operations.
+ */
+ PREF( 0, 0(src) )
+ PREF( 1, 0(dst) )
+ sltu t2, len, NBYTES
+ and t1, dst, ADDRMASK
+ PREF( 0, 1*32(src) )
+ PREF( 1, 1*32(dst) )
+ bnez t2, copy_bytes_checklen
+ and t0, src, ADDRMASK
+ PREF( 0, 2*32(src) )
+ PREF( 1, 2*32(dst) )
+ bnez t1, dst_unaligned
+ nop
+ bnez t0, src_unaligned_dst_aligned
+ /*
+ * use delay slot for fall-through
+ * src and dst are aligned; need to compute rem
+ */
+both_aligned:
+ SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
+ beqz t0, cleanup_both_aligned # len < 8*NBYTES
+ and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES)
+ PREF( 0, 3*32(src) )
+ PREF( 1, 3*32(dst) )
+ .align 4
+1:
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 8*NBYTES
+EXC( LOAD t4, UNIT(4)(src), l_exc_copy)
+EXC( LOAD t7, UNIT(5)(src), l_exc_copy)
+EXC( STORE t0, UNIT(0)(dst), s_exc_p8u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p7u)
+EXC( LOAD t0, UNIT(6)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(7)(src), l_exc_copy)
+ ADD src, src, 8*NBYTES
+ ADD dst, dst, 8*NBYTES
+EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u)
+EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u)
+EXC( STORE t4, UNIT(-4)(dst), s_exc_p4u)
+EXC( STORE t7, UNIT(-3)(dst), s_exc_p3u)
+EXC( STORE t0, UNIT(-2)(dst), s_exc_p2u)
+EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u)
+ PREF( 0, 8*32(src) )
+ PREF( 1, 8*32(dst) )
+ bne len, rem, 1b
+ nop
+
+ /*
+ * len == rem == the number of bytes left to copy < 8*NBYTES
+ */
+cleanup_both_aligned:
+ beqz len, done
+ sltu t0, len, 4*NBYTES
+ bnez t0, less_than_4units
+ and rem, len, (NBYTES-1) # rem = len % NBYTES
+ /*
+ * len >= 4*NBYTES
+ */
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+ ADD src, src, 4*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ beqz len, done
+ ADD dst, dst, 4*NBYTES
+less_than_4units:
+ /*
+ * rem = len % NBYTES
+ */
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LOAD t0, 0(src), l_exc)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ bne rem, len, 1b
+ ADD dst, dst, NBYTES
+
+ /*
+ * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
+ * A loop would do only a byte at a time with possible branch
+ * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE
+ * because can't assume read-access to dst. Instead, use
+ * STREST dst, which doesn't require read access to dst.
+ *
+ * This code should perform better than a simple loop on modern,
+ * wide-issue mips processors because the code has fewer branches and
+ * more instruction-level parallelism.
+ */
+#define bits t2
+ beqz len, done
+ ADD t1, dst, len # t1 is just past last byte of dst
+ li bits, 8*NBYTES
+ SLL rem, len, 3 # rem = number of bits to keep
+EXC( LOAD t0, 0(src), l_exc)
+ SUB bits, bits, rem # bits = number of bits to discard
+ SHIFT_DISCARD t0, t0, bits
+EXC( STREST t0, -1(t1), s_exc)
+ jr ra
+ move len, zero
+dst_unaligned:
+ /*
+ * dst is unaligned
+ * t0 = src & ADDRMASK
+ * t1 = dst & ADDRMASK; T1 > 0
+ * len >= NBYTES
+ *
+ * Copy enough bytes to align dst
+ * Set match = (src and dst have same alignment)
+ */
+#define match rem
+EXC( LDFIRST t3, FIRST(0)(src), l_exc)
+ ADD t2, zero, NBYTES
+EXC( LDREST t3, REST(0)(src), l_exc_copy)
+ SUB t2, t2, t1 # t2 = number of bytes copied
+ xor match, t0, t1
+EXC( STFIRST t3, FIRST(0)(dst), s_exc)
+ beq len, t2, done
+ SUB len, len, t2
+ ADD dst, dst, t2
+ beqz match, both_aligned
+ ADD src, src, t2
+
+src_unaligned_dst_aligned:
+ SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
+ PREF( 0, 3*32(src) )
+ beqz t0, cleanup_src_unaligned
+ and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
+ PREF( 1, 3*32(dst) )
+1:
+/*
+ * Avoid consecutive LD*'s to the same register since some mips
+ * implementations can't issue them in the same cycle.
+ * It's OK to load FIRST(N+1) before REST(N) because the two addresses
+ * are to the same unit (unless src is aligned, but it's not).
+ */
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+EXC( LDREST t1, REST(1)(src), l_exc_copy)
+EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy)
+EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy)
+EXC( LDREST t2, REST(2)(src), l_exc_copy)
+EXC( LDREST t3, REST(3)(src), l_exc_copy)
+ PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
+ ADD src, src, 4*NBYTES
+#ifdef CONFIG_CPU_SB1
+ nop # improves slotting
+#endif
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
+ bne len, rem, 1b
+ ADD dst, dst, 4*NBYTES
+
+cleanup_src_unaligned:
+ beqz len, done
+ and rem, len, NBYTES-1 # rem = len % NBYTES
+ beq rem, len, copy_bytes
+1:
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ bne len, rem, 1b
+ ADD dst, dst, NBYTES
+
+copy_bytes_checklen:
+ beqz len, done
+ nop
+copy_bytes:
+ /* 0 < len < NBYTES */
+#define COPY_BYTE(N) \
+EXC( lb t0, N(src), l_exc); \
+ SUB len, len, 1; \
+ beqz len, done; \
+EXC( sb t0, N(dst), s_exc_p1)
+
+ COPY_BYTE(0)
+ COPY_BYTE(1)
+#ifdef USE_DOUBLE
+ COPY_BYTE(2)
+ COPY_BYTE(3)
+ COPY_BYTE(4)
+ COPY_BYTE(5)
+#endif
+EXC( lb t0, NBYTES-2(src), l_exc)
+ SUB len, len, 1
+ jr ra
+EXC( sb t0, NBYTES-2(dst), s_exc_p1)
+done:
+ jr ra
+ nop
+ END(memcpy)
+
+l_exc_copy:
+ /*
+ * Copy bytes from src until faulting load address (or until a
+ * lb faults)
+ *
+ * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
+ * may be more than a byte beyond the last address.
+ * Hence, the lb below may get an exception.
+ *
+ * Assumes src < THREAD_BUADDR($28)
+ */
+ LOAD t0, THREAD_BUADDR($28)
+1:
+EXC( lb t1, 0(src), l_exc)
+ ADD src, src, 1
+ sb t1, 0(dst) # can't fault -- we're copy_from_user
+ bne src, t0, 1b
+ ADD dst, dst, 1
+l_exc:
+ LOAD t0, THREAD_BUADDR($28) # t0 is just past last good address
+ nop
+ SUB len, AT, t0 # len number of uncopied bytes
+ /*
+ * Here's where we rely on src and dst being incremented in tandem,
+ * See (3) above.
+ * dst += (fault addr - src) to put dst at first byte to clear
+ */
+ ADD dst, t0 # compute start address in a1
+ SUB dst, src
+ /*
+ * Clear len bytes starting at dst. Can't call __bzero because it
+ * might modify len. An inefficient loop for these rare times...
+ */
+ beqz len, done
+ SUB src, len, 1
+1: sb zero, 0(dst)
+ ADD dst, dst, 1
+ bnez src, 1b
+ SUB src, src, 1
+ jr ra
+ nop
+
+
+#define SEXC(n) \
+s_exc_p ## n ## u: \
+ jr ra; \
+ ADD len, len, n*NBYTES
+
+SEXC(8)
+SEXC(7)
+SEXC(6)
+SEXC(5)
+SEXC(4)
+SEXC(3)
+SEXC(2)
+SEXC(1)
+
+s_exc_p1:
+ jr ra
+ ADD len, len, 1
+s_exc:
+ jr ra
+ nop
+
+ .align 5
+LEAF(memmove)
+ ADD t0, a0, a2
+ ADD t1, a1, a2
+ sltu t0, a1, t0 # dst + len <= src -> memcpy
+ sltu t1, a0, t1 # dst >= src + len -> memcpy
+ and t0, t1
+ beqz t0, __memcpy
+ move v0, a0 /* return value */
+ beqz a2, r_out
+ END(memmove)
+
+ /* fall through to __rmemcpy */
+LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
+ sltu t0, a1, a0
+ beqz t0, r_end_bytes_up # src >= dst
+ nop
+ ADD a0, a2 # dst = dst + len
+ ADD a1, a2 # src = src + len
+
+r_end_bytes:
+ lb t0, -1(a1)
+ SUB a2, a2, 0x1
+ sb t0, -1(a0)
+ SUB a1, a1, 0x1
+ bnez a2, r_end_bytes
+ SUB a0, a0, 0x1
+
+r_out:
+ jr ra
+ move a2, zero
+
+r_end_bytes_up:
+ lb t0, (a1)
+ SUB a2, a2, 0x1
+ sb t0, (a0)
+ ADD a1, a1, 0x1
+ bnez a2, r_end_bytes_up
+ ADD a0, a0, 0x1
+
+ jr ra
+ move a2, zero
+ END(__rmemcpy)
diff --git a/release/src/linux/linux/arch/mips/lib/memset.S b/release/src/linux/linux/arch/mips/lib/memset.S
new file mode 100644
index 00000000..3371a153
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/memset.S
@@ -0,0 +1,141 @@
+/*
+ * 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 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+#define F_FILL64(dst, offset, val, fixup) \
+ EX(sw, val, (offset + 0x00)(dst), fixup); \
+ EX(sw, val, (offset + 0x04)(dst), fixup); \
+ EX(sw, val, (offset + 0x08)(dst), fixup); \
+ EX(sw, val, (offset + 0x0c)(dst), fixup); \
+ EX(sw, val, (offset + 0x10)(dst), fixup); \
+ EX(sw, val, (offset + 0x14)(dst), fixup); \
+ EX(sw, val, (offset + 0x18)(dst), fixup); \
+ EX(sw, val, (offset + 0x1c)(dst), fixup); \
+ EX(sw, val, (offset + 0x20)(dst), fixup); \
+ EX(sw, val, (offset + 0x24)(dst), fixup); \
+ EX(sw, val, (offset + 0x28)(dst), fixup); \
+ EX(sw, val, (offset + 0x2c)(dst), fixup); \
+ EX(sw, val, (offset + 0x30)(dst), fixup); \
+ EX(sw, val, (offset + 0x34)(dst), fixup); \
+ EX(sw, val, (offset + 0x38)(dst), fixup); \
+ EX(sw, val, (offset + 0x3c)(dst), fixup)
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+ .set noreorder
+ .align 5
+LEAF(memset)
+ beqz a1, 1f
+ move v0, a0 /* result */
+
+ andi a1, 0xff /* spread fillword */
+ sll t1, a1, 8
+ or a1, t1
+ sll t1, a1, 16
+ or a1, t1
+1:
+
+EXPORT(__bzero)
+ sltiu t0, a2, 4 /* very small region? */
+ bnez t0, small_memset
+ andi t0, a0, 3 /* aligned? */
+
+ beqz t0, 1f
+ subu t0, 4 /* alignment in bytes */
+
+#ifdef __MIPSEB__
+ EX(swl, a1, (a0), first_fixup) /* make word aligned */
+#endif
+#ifdef __MIPSEL__
+ EX(swr, a1, (a0), first_fixup) /* make word aligned */
+#endif
+ subu a0, t0 /* word align ptr */
+ addu a2, t0 /* correct size */
+
+1: ori t1, a2, 0x3f /* # of full blocks */
+ xori t1, 0x3f
+ beqz t1, memset_partial /* no block to fill */
+ andi t0, a2, 0x3c
+
+ addu t1, a0 /* end address */
+ .set reorder
+1: addiu a0, 64
+ F_FILL64(a0, -64, a1, fwd_fixup)
+ bne t1, a0, 1b
+ .set noreorder
+
+memset_partial:
+ PTR_LA t1, 2f /* where to start */
+ subu t1, t0
+ jr t1
+ addu a0, t0 /* dest ptr */
+
+ .set push
+ .set noreorder
+ .set nomacro
+ F_FILL64(a0, -64, a1, partial_fixup) /* ... but first do wrds ... */
+2: .set pop
+ andi a2, 3 /* 0 <= n <= 3 to go */
+
+ beqz a2, 1f
+ addu a0, a2 /* What's left */
+#ifdef __MIPSEB__
+ EX(swr, a1, -1(a0), last_fixup)
+#endif
+#ifdef __MIPSEL__
+ EX(swl, a1, -1(a0), last_fixup)
+#endif
+1: jr ra
+ move a2, zero
+
+small_memset:
+ beqz a2, 2f
+ addu t1, a0, a2
+
+1: addiu a0, 1 /* fill bytewise */
+ bne t1, a0, 1b
+ sb a1, -1(a0)
+
+2: jr ra /* done */
+ move a2, zero
+ END(memset)
+
+first_fixup:
+ jr ra
+ nop
+
+fwd_fixup:
+ lw t0, THREAD_BUADDR($28)
+ andi a2, 0x3f
+ addu a2, t1
+ jr ra
+ subu a2, t0
+
+partial_fixup:
+ lw t0, THREAD_BUADDR($28)
+ andi a2, 3
+ addu a2, t1
+ jr ra
+ subu a2, t0
+
+last_fixup:
+ jr ra
+ andi v1, a2, 3
diff --git a/release/src/linux/linux/arch/mips/lib/promlib.c b/release/src/linux/linux/arch/mips/lib/promlib.c
new file mode 100644
index 00000000..dddfe98b
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/promlib.c
@@ -0,0 +1,24 @@
+#include <stdarg.h>
+#include <linux/kernel.h>
+
+extern void prom_putchar(char);
+
+void prom_printf(char *fmt, ...)
+{
+ va_list args;
+ char ppbuf[1024];
+ char *bptr;
+
+ va_start(args, fmt);
+ vsprintf(ppbuf, fmt, args);
+
+ bptr = ppbuf;
+
+ while (*bptr != 0) {
+ if (*bptr == '\n')
+ prom_putchar('\r');
+
+ prom_putchar(*bptr++);
+ }
+ va_end(args);
+}
diff --git a/release/src/linux/linux/arch/mips/lib/r3k_dump_tlb.c b/release/src/linux/linux/arch/mips/lib/r3k_dump_tlb.c
new file mode 100644
index 00000000..b6f08083
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/r3k_dump_tlb.c
@@ -0,0 +1,187 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
+
+void
+dump_tlb(int first, int last)
+{
+ int i;
+ unsigned int asid;
+ unsigned long entryhi, entrylo0;
+
+ asid = read_c0_entryhi() & 0xfc0;
+
+ for(i=first;i<=last;i++)
+ {
+ write_c0_index(i<<8);
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ "tlbr\n\t"
+ "nop\n\t"
+ ".set\treorder");
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+
+ /* Unused entries have a virtual address of KSEG0. */
+ if ((entryhi & 0xffffe000) != 0x80000000
+ && (entryhi & 0xfc0) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d ", i);
+
+ printk("va=%08lx asid=%08lx"
+ " [pa=%06lx n=%d d=%d v=%d g=%d]",
+ (entryhi & 0xffffe000),
+ entryhi & 0xfc0,
+ entrylo0 & PAGE_MASK,
+ (entrylo0 & (1 << 11)) ? 1 : 0,
+ (entrylo0 & (1 << 10)) ? 1 : 0,
+ (entrylo0 & (1 << 9)) ? 1 : 0,
+ (entrylo0 & (1 << 8)) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(asid);
+}
+
+void
+dump_tlb_all(void)
+{
+ dump_tlb(0, mips_cpu.tlbsize - 1);
+}
+
+void
+dump_tlb_wired(void)
+{
+ int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
+
+ printk("Wired: %d", wired);
+ dump_tlb(0, wired - 1);
+}
+
+void
+dump_tlb_addr(unsigned long addr)
+{
+ unsigned int flags, oldpid;
+ int index;
+
+ __save_and_cli(flags);
+ oldpid = read_c0_entryhi() & 0xff;
+ write_c0_entryhi((addr & PAGE_MASK) | oldpid);
+ tlb_probe();
+ index = read_c0_index();
+ write_c0_entryhi(oldpid);
+ __restore_flags(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
+void
+dump_tlb_nonwired(void)
+{
+ int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
+ dump_tlb(wired, mips_cpu.tlbsize - 1);
+}
+
+void
+dump_list_process(struct task_struct *t, void *address)
+{
+ pgd_t *page_dir, *pgd;
+ pmd_t *pmd;
+ pte_t *pte, page;
+ unsigned int addr;
+ unsigned long val;
+
+ addr = (unsigned int) address;
+
+ printk("Addr == %08x\n", addr);
+ printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
+
+ page_dir = pgd_offset(t->mm, 0);
+ printk("page_dir == %08x\n", (unsigned int) page_dir);
+
+ pgd = pgd_offset(t->mm, addr);
+ printk("pgd == %08x, ", (unsigned int) pgd);
+
+ pmd = pmd_offset(pgd, addr);
+ printk("pmd == %08x, ", (unsigned int) pmd);
+
+ pte = pte_offset(pmd, addr);
+ printk("pte == %08x, ", (unsigned int) pte);
+
+ page = *pte;
+ printk("page == %08x\n", (unsigned int) pte_val(page));
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
+}
+
+void
+dump_list_current(void *address)
+{
+ dump_list_process(current, address);
+}
+
+unsigned int
+vtop(void *address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned int addr, paddr;
+
+ addr = (unsigned long) address;
+ pgd = pgd_offset(current->mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+ paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+ paddr |= (addr & ~PAGE_MASK);
+
+ return paddr;
+}
+
+void
+dump16(unsigned long *p)
+{
+ int i;
+
+ for(i=0;i<8;i++)
+ {
+ printk("*%08lx == %08lx, ",
+ (unsigned long)p, (unsigned long)*p++);
+ printk("*%08lx == %08lx\n",
+ (unsigned long)p, (unsigned long)*p++);
+ }
+}
diff --git a/release/src/linux/linux/arch/mips/lib/rtc-no.c b/release/src/linux/linux/arch/mips/lib/rtc-no.c
new file mode 100644
index 00000000..a8f01eea
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/rtc-no.c
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ *
+ * Stub RTC routines to keep Linux from crashing on machine which don't
+ * have a RTC chip.
+ *
+ * Copyright (C) 1998, 2001 by Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+
+static unsigned int shouldnt_happen(void)
+{
+ static int called;
+
+ if (!called) {
+ called = 1;
+ printk(KERN_DEBUG "RTC functions called - shouldn't happen\n");
+ }
+
+ return 0;
+}
+
+struct rtc_ops no_rtc_ops = {
+ .rtc_read_data = (void *) &shouldnt_happen,
+ .rtc_write_data = (void *) &shouldnt_happen,
+ .rtc_bcd_mode = (void *) &shouldnt_happen
+};
diff --git a/release/src/linux/linux/arch/mips/lib/rtc-std.c b/release/src/linux/linux/arch/mips/lib/rtc-std.c
new file mode 100644
index 00000000..e36d02d2
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/rtc-std.c
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ * RTC routines for PC style attached Dallas chip.
+ *
+ * Copyright (C) 1998, 2001 by Ralf Baechle
+ */
+#include <linux/mc146818rtc.h>
+#include <asm/io.h>
+
+static unsigned char std_rtc_read_data(unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ return inb_p(RTC_PORT(1));
+}
+
+static void std_rtc_write_data(unsigned char data, unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ outb_p(data, RTC_PORT(1));
+}
+
+static int std_rtc_bcd_mode(void)
+{
+ return 1;
+}
+
+struct rtc_ops std_rtc_ops = {
+ &std_rtc_read_data,
+ &std_rtc_write_data,
+ &std_rtc_bcd_mode
+};
diff --git a/release/src/linux/linux/arch/mips/lib/strlen_user.S b/release/src/linux/linux/arch/mips/lib/strlen_user.S
new file mode 100644
index 00000000..e179f28c
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/strlen_user.S
@@ -0,0 +1,40 @@
+/*
+ * 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, 1998, 1999 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+LEAF(__strlen_user_asm)
+ lw v0, THREAD_CURDS($28) # pointer ok?
+ and v0, a0
+ bltz v0, fault
+
+FEXPORT(__strlen_user_nocheck_asm)
+ move v0, a0
+1: EX(lb, t0, (v0), fault)
+ addiu v0, 1
+ bnez t0, 1b
+ subu v0, a0
+ jr ra
+ END(__strlen_user_asm)
+
+fault: move v0, zero
+ jr ra
diff --git a/release/src/linux/linux/arch/mips/lib/strncpy_user.S b/release/src/linux/linux/arch/mips/lib/strncpy_user.S
new file mode 100644
index 00000000..3d91eb8e
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/strncpy_user.S
@@ -0,0 +1,58 @@
+/*
+ * 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, 1999 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ */
+
+/*
+ * Ugly special case have to check: we might get passed a user space
+ * pointer which wraps into the kernel space. We don't deal with that. If
+ * it happens at most some bytes of the exceptions handlers will be copied.
+ */
+
+LEAF(__strncpy_from_user_asm)
+ lw v0, THREAD_CURDS($28) # pointer ok?
+ and v0, a1
+ bltz v0, fault
+
+EXPORT(__strncpy_from_user_nocheck_asm)
+ move v0, zero
+ move v1, a1
+ .set noreorder
+1: EX(lbu, t0, (v1), fault)
+ addiu v1, v1, 1
+ beqz t0, 2f
+ sb t0, (a0)
+ addiu v0, 1
+ bne v0, a2, 1b
+ addiu a0, 1
+ .set reorder
+2: addu t0, a1, v0
+ xor t0, a1
+ bltz t0, fault
+ jr ra # return n
+ END(__strncpy_from_user_asm)
+
+fault: li v0, -EFAULT
+ jr ra
+
+ .section __ex_table,"a"
+ PTR 1b, fault
+ .previous
diff --git a/release/src/linux/linux/arch/mips/lib/strnlen_user.S b/release/src/linux/linux/arch/mips/lib/strnlen_user.S
new file mode 100644
index 00000000..83b77d04
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/strnlen_user.S
@@ -0,0 +1,49 @@
+/*
+ * 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, 1998, 1999 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error, len of string but at max a1 otherwise
+ *
+ * Note: for performance reasons we deliberately accept that a user may
+ * make strlen_user and strnlen_user access the first few KSEG0
+ * bytes. There's nothing secret there ...
+ */
+LEAF(__strnlen_user_asm)
+ lw v0, THREAD_CURDS($28) # pointer ok?
+ and v0, a0
+ bltz v0, fault
+
+FEXPORT(__strnlen_user_nocheck_asm)
+ .type __strnlen_user_nocheck_asm,@function
+ move v0, a0
+ addu a1, a0 # stop pointer
+ .set noreorder
+1: beq v0, a1, 1f # limit reached?
+ addiu v0, 1
+ .set reorder
+ EX(lb, t0, -1(v0), fault)
+ bnez t0, 1b
+1: subu v0, a0
+ jr ra
+ END(__strnlen_user_asm)
+
+fault: move v0, zero
+ jr ra
diff --git a/release/src/linux/linux/arch/mips/lib/tinycon.c b/release/src/linux/linux/arch/mips/lib/tinycon.c
new file mode 100644
index 00000000..5bf6ddd4
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/tinycon.c
@@ -0,0 +1,119 @@
+
+
+#include <linux/tty.h>
+#include <asm/bootinfo.h>
+
+static unsigned int size_x;
+static unsigned int size_y;
+static unsigned short cursor_x;
+static unsigned short cursor_y;
+static volatile unsigned short *vram_addr;
+static int console_needs_init = 1;
+
+extern struct screen_info screen_info;
+
+/* ----------------------------------------------------------------------
+ * init_console()
+ * ---------------------------------------------------------------------- */
+
+void init_console(void)
+{
+ size_x = 80;
+ size_y = 25;
+ cursor_x = 0;
+ cursor_y = 0;
+
+ vram_addr = (unsigned short *)0xb00b8000;
+
+ console_needs_init = 0;
+}
+
+void
+set_size_x(unsigned int x)
+{
+ size_x = x;
+}
+
+void
+set_size_y(unsigned int y)
+{
+ size_y = y;
+}
+
+void
+set_vram(unsigned short *vram)
+{
+ vram_addr = vram;
+}
+
+void
+set_crsr(unsigned int x, unsigned int y)
+{
+ cursor_x = x;
+ cursor_y = y;
+}
+
+void
+print_char(unsigned int x, unsigned int y, unsigned char c)
+{
+ volatile unsigned short *caddr;
+
+ caddr = vram_addr + (y * size_x) + x;
+ *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c;
+}
+
+static void
+scroll(void)
+{
+ volatile unsigned short *caddr;
+ register int i;
+
+ caddr = vram_addr;
+ for(i=0; i<size_x * (size_y-1); i++)
+ *(caddr++) = *(caddr + size_x);
+
+ /* blank last line */
+
+ caddr = vram_addr + (size_x * (size_y-1));
+ for(i=0; i<size_x; i++)
+ *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
+}
+
+void print_string(const unsigned char *str)
+{
+ unsigned char c;
+
+ if (console_needs_init)
+ init_console();
+
+ while((c = *str++))
+ switch(c)
+ {
+ case '\n':
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ break;
+
+ default:
+ print_char(cursor_x, cursor_y, c);
+ cursor_x++;
+ if(cursor_x == size_x)
+ {
+ cursor_x = 0;
+ cursor_y++;
+ if(cursor_y == size_y)
+ {
+ scroll();
+ cursor_y = size_y - 1;
+ }
+ }
+ break;
+ }
+}
+
+/* end of file */
diff --git a/release/src/linux/linux/arch/mips/lib/watch.S b/release/src/linux/linux/arch/mips/lib/watch.S
new file mode 100644
index 00000000..f42cf5da
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/lib/watch.S
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ * Kernel debug stuff to use the Watch registers.
+ * Useful to find stack overflows, dangling pointers etc.
+ *
+ * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+ .set noreorder
+/*
+ * Parameter: a0 - logic address to watch
+ * Currently only KSEG0 addresses are allowed!
+ * a1 - set bit #1 to trap on load references
+ * bit #0 to trap on store references
+ * Results : none
+ */
+ LEAF(__watch_set)
+ li t0,0x80000000
+ subu a0,t0
+ ori a0,7
+ xori a0,7
+ or a0,a1
+ mtc0 a0,CP0_WATCHLO
+ sw a0,watch_savelo
+
+ jr ra
+ mtc0 zero,CP0_WATCHHI
+ END(__watch_set)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_clear)
+ jr ra
+ mtc0 zero,CP0_WATCHLO
+ END(__watch_clear)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_reenable)
+ lw t0,watch_savelo
+ jr ra
+ mtc0 t0,CP0_WATCHLO
+ END(__watch_reenable)
+
+/*
+ * Saved value of the c0_watchlo register for watch_reenable()
+ */
+ .data
+watch_savelo: .word 0
+ .text