summaryrefslogtreecommitdiffstats
path: root/include/asm-mips
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-mips')
-rw-r--r--include/asm-mips/bitops.h165
-rw-r--r--include/asm-mips/bootinfo.h63
-rw-r--r--include/asm-mips/cachectl.h32
-rw-r--r--include/asm-mips/delay.h25
-rw-r--r--include/asm-mips/dma.h271
-rw-r--r--include/asm-mips/head.h9
-rw-r--r--include/asm-mips/in.h34
-rw-r--r--include/asm-mips/interrupt.h40
-rw-r--r--include/asm-mips/io.h240
-rw-r--r--include/asm-mips/irq.h18
-rw-r--r--include/asm-mips/mipsconfig.h29
-rw-r--r--include/asm-mips/mipsregs.h111
-rw-r--r--include/asm-mips/mm.h94
-rw-r--r--include/asm-mips/page.h90
-rw-r--r--include/asm-mips/ptrace.h110
-rw-r--r--include/asm-mips/regdef.h50
-rw-r--r--include/asm-mips/sched.h240
-rw-r--r--include/asm-mips/segment.h28
-rw-r--r--include/asm-mips/signal.h28
-rw-r--r--include/asm-mips/slots.h17
-rw-r--r--include/asm-mips/stackframe.h176
-rw-r--r--include/asm-mips/string.h25
-rw-r--r--include/asm-mips/system.h83
-rw-r--r--include/asm-mips/types.h39
-rw-r--r--include/asm-mips/unistd.h12
25 files changed, 1956 insertions, 73 deletions
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 9665c7f01..a2fd7972b 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -7,14 +7,167 @@
*
* Copyright (c) 1994 by Ralf Baechle
*/
+#ifndef _ASM_MIPS_BITOPS_H
+#define _ASM_MIPS_BITOPS_H
-#ifndef _ASM_MIPS_BITOPS_H_
-#define _ASM_MIPS_BITOPS_H_
+#include <asm/mipsregs.h>
+
+extern inline int set_bit(int nr, void *addr)
+{
+ int mask, retval, mw;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ do {
+ mw = load_linked(addr);
+ retval = (mask & mw) != 0;
+ }
+ while (!store_conditional(addr, mw|mask));
+
+ return retval;
+}
+
+extern inline int clear_bit(int nr, void *addr)
+{
+ int mask, retval, mw;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ do {
+ mw = load_linked(addr);
+ retval = (mask & mw) != 0;
+ }
+ while (!store_conditional(addr, mw & ~mask));
+
+ return retval;
+}
+
+extern inline int change_bit(int nr, void *addr)
+{
+ int mask, retval, mw;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ do {
+ mw = load_linked(addr);
+ retval = (mask & mw) != 0;
+ }
+ while (!store_conditional(addr, mw ^ mask));
+
+ return retval;
+}
+
+extern inline int test_bit(int nr, void *addr)
+{
+ int mask;
+ int *a;
+
+ a = addr;
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ return ((mask & *a) != 0);
+}
+
+
+/*
+ * The above written is not true for the bitfield functions.
+ */
+static inline int find_first_zero_bit (void *addr, unsigned size)
+{
+ int res;
+
+ if (!size)
+ return 0;
+
+ __asm__(".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+ "1:\tsubu\t$1,%2,%0\n\t"
+ "blez\t$1,2f\n\t"
+ "lw\t$1,(%4)\n\t"
+ "addiu\t%4,%4,4\n\t"
+ "beql\t%1,$1,1b\n\t"
+ "addiu\t%0,%0,32\n\t"
+ "li\t%1,1\n"
+ "1:\tand\t%4,$1,%1\n\t"
+ "beq\t$0,%4,2f\n\t"
+ "sll\t%1,%1,1\n\t"
+ "bne\t$0,%1,1b\n\t"
+ "add\t%0,%0,1\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n"
+ "2:"
+ : "=d" (res)
+ : "d" ((unsigned int) 0xffffffff),
+ "d" (size),
+ "0" ((signed int) 0),
+ "d" (addr)
+ : "$1");
+
+ return res;
+}
+
+static inline int find_next_zero_bit (void * addr, int size, int offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+ int set = 0, bit = offset & 31, res;
+
+ if (bit) {
+ /*
+ * Look for zero in first byte
+ */
+ __asm__(".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+ "1:\tand\t$1,%2,%1\n\t"
+ "beq\t$0,$1,2f\n\t"
+ "sll\t%2,%2,1\n\t"
+ "bne\t$0,%2,1b\n\t"
+ "addiu\t%0,%0,1\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n"
+ : "=r" (set)
+ : "r" (*p >> bit),
+ "r" (1),
+ "0" (0));
+ if (set < (32 - bit))
+ return set + offset;
+ set = 32 - bit;
+ p++;
+ }
+ /*
+ * No zero yet, search remaining full bytes for a zero
+ */
+ res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
+ return (offset + set + res);
+}
/*
- * On MIPS inline assembler bitfunctions are as effective
- * as the standard C counterparts.
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
*/
-#include <asm-generic/bitops.h>
+extern inline unsigned long ffz(unsigned long word)
+{
+ unsigned int __res;
+ unsigned int mask = 1;
+
+ __asm__ __volatile__ (
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ "li\t%2,1\n"
+ "1:\tand\t$1,%2,%1\n\t"
+ "beq\t$0,$1,2f\n\t"
+ "sll\t%2,%2,1\n\t"
+ "bne\t$0,%2,1b\n\t"
+ "add\t%0,%0,1\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n"
+ "2:\n\t"
+ : "=r" (__res), "=r" (word), "=r" (mask)
+ : "1" (~(word)),
+ "2" (mask),
+ "0" (0)
+ : "$1");
+
+ return __res;
+}
-#endif /* _ASM_MIPS_BITOPS_H_ */
+#endif /* _ASM_MIPS_BITOPS_H */
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
new file mode 100644
index 000000000..4ff415bf1
--- /dev/null
+++ b/include/asm-mips/bootinfo.h
@@ -0,0 +1,63 @@
+/*
+ * bootinfo.h -- Definition of the Linux/68K boot information structure
+ *
+ * Written by Ralf Baechle,
+ * Copyright (C) 1994 by Waldorf GMBH
+ *
+ * Based on Linux/68k linux/include/linux/bootstrap.h
+ * Copyright (C) 1992 by Greg Harp
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef ASM_MIPS_BOOTINFO_H
+#define ASM_MIPS_BOOTINFO_H
+
+/*
+ * Valid values for machtype field
+ */
+#define MACH_DESKSTATION_TYNE 1 /* Deskstation Tyne */
+
+/*
+ * Type of CPU
+ */
+#define CPU_R4600 1
+
+#define CL_SIZE (80)
+
+struct bootinfo {
+ unsigned long
+ machtype; /* machine type */
+
+ unsigned long
+ cputype; /* system CPU & FPU */
+
+ /*
+ * Installed RAM
+ */
+ unsigned int memlower;
+ unsigned int memupper;
+
+ /*
+ * Cache Information
+ */
+ unsigned int sec_cache;
+ unsigned int dma_cache;
+
+ unsigned long
+ ramdisk_size; /* ramdisk size in 1024 byte blocks */
+
+ unsigned long
+ ramdisk_addr; /* address of the ram disk in mem */
+
+ char
+ command_line[CL_SIZE]; /* kernel command line parameters */
+
+};
+
+extern struct bootinfo
+ boot_info;
+
+#endif /* ASM_MIPS_BOOTINFO_H */
diff --git a/include/asm-mips/cachectl.h b/include/asm-mips/cachectl.h
new file mode 100644
index 000000000..167727c97
--- /dev/null
+++ b/include/asm-mips/cachectl.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-mips/cachectl.h
+ *
+ * Written by Ralf Baechle,
+ * Copyright (C) 1994 by Waldorf GMBH
+ *
+ * Defines for Risc/OS compatible cacheflush systemcall
+ */
+#ifndef _ASM_MIPS_CACHECTL
+#define _ASM_MIPS_CACHECTL
+
+/*
+ * cachectl.h -- defines for MIPS cache control system calls
+ */
+
+/*
+ * Options for cacheflush system call
+ */
+#define ICACHE (1<<0) /* flush instruction cache */
+#define DCACHE (1<<1) /* writeback and flush data cache */
+#define BCACHE (ICACHE|DCACHE) /* flush both caches */
+
+#define CACHELINES 512 /* number of cachelines */
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+extern int sys_cacheflush(void *addr, int nbytes, int cache);
+
+#endif
+#endif
+#endif /* _ASM_MIPS_CACHECTL */
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index 09fd0c470..5aa85e165 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -1,13 +1,17 @@
-#ifndef _MIPS_DELAY_H
-#define _MIPS_DELAY_H
+#ifndef _ASM_MIPS_DELAY_H
+#define _ASM_MIPS_DELAY_H
extern __inline__ void __delay(int loops)
{
- __asm__(".align 3\n"
- "1:\tbeq\t$0,%0,1b\n\t"
- "addiu\t%0,%0,-1\n\t"
- :
- :"d" (loops));
+ __asm__ __volatile__ (
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ "1:\tbne\t$0,%0,1b\n\t"
+ "subu\t%0,%0,1\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (loops)
+ :"0" (loops));
}
/*
@@ -24,10 +28,9 @@ extern __inline__ void udelay(unsigned long usecs)
{
usecs *= 0x000010c6; /* 2**32 / 1000000 */
__asm__("mul\t%0,%0,%1"
- :"=d" (usecs)
- :"0" (usecs),"d" (loops_per_sec)
- :"ax");
+ :"=r" (usecs)
+ :"0" (usecs),"r" (loops_per_sec));
__delay(usecs);
}
-#endif /* defined(_MIPS_DELAY_H) */
+#endif /* defined (_ASM_MIPS_DELAY_H) */
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h
new file mode 100644
index 000000000..7540aedec
--- /dev/null
+++ b/include/asm-mips/dma.h
@@ -0,0 +1,271 @@
+/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ * Written by Hennus Bergman, 1992.
+ * High DMA channel support & info by Hannu Savolainen
+ * and John Boyd, Nov. 1992.
+ */
+
+#ifndef _ASM_MIPS_DMA_H
+#define _ASM_MIPS_DMA_H
+
+#include <asm/io.h> /* need byte IO */
+
+
+#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#define dma_outb outb_p
+#else
+#define dma_outb outb
+#endif
+
+#define dma_inb inb
+
+/*
+ * NOTES about DMA transfers:
+ *
+ * controller 1: channels 0-3, byte operations, ports 00-1F
+ * controller 2: channels 4-7, word operations, ports C0-DF
+ *
+ * - ALL registers are 8 bits only, regardless of transfer size
+ * - channel 4 is not used - cascades 1 into 2.
+ * - channels 0-3 are byte - addresses/counts are for physical bytes
+ * - channels 5-7 are word - addresses/counts are for physical words
+ * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+ * - transfer count loaded to registers is 1 less than actual count
+ * - controller 2 offsets are all even (2x offsets for controller 1)
+ * - page registers for 5-7 don't use data bit 0, represent 128K pages
+ * - page registers for 0-3 use bit 0, represent 64K pages
+ *
+ * DMA transfers are limited to the lower 16MB of _physical_ memory.
+ * Note that addresses loaded into registers must be _physical_ addresses,
+ * not logical addresses (which may differ if paging is active).
+ *
+ * Address mapping for channels 0-3:
+ *
+ * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
+ * | ... | | ... | | ... |
+ * | ... | | ... | | ... |
+ * | ... | | ... | | ... |
+ * P7 ... P0 A7 ... A0 A7 ... A0
+ * | Page | Addr MSB | Addr LSB | (DMA registers)
+ *
+ * Address mapping for channels 5-7:
+ *
+ * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
+ * | ... | \ \ ... \ \ \ ... \ \
+ * | ... | \ \ ... \ \ \ ... \ (not used)
+ * | ... | \ \ ... \ \ \ ... \
+ * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
+ * | Page | Addr MSB | Addr LSB | (DMA registers)
+ *
+ * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+ * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+ * the hardware level, so odd-byte transfers aren't possible).
+ *
+ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+ * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
+ * and up to 128K bytes may be transferred on channels 5-7 in one operation.
+ *
+ */
+
+#define MAX_DMA_CHANNELS 8
+
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS 0xffffff
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+#define DMA_ADDR_0 0x00 /* DMA address registers */
+#define DMA_ADDR_1 0x02
+#define DMA_ADDR_2 0x04
+#define DMA_ADDR_3 0x06
+#define DMA_ADDR_4 0xC0
+#define DMA_ADDR_5 0xC4
+#define DMA_ADDR_6 0xC8
+#define DMA_ADDR_7 0xCC
+
+#define DMA_CNT_0 0x01 /* DMA count registers */
+#define DMA_CNT_1 0x03
+#define DMA_CNT_2 0x05
+#define DMA_CNT_3 0x07
+#define DMA_CNT_4 0xC2
+#define DMA_CNT_5 0xC6
+#define DMA_CNT_6 0xCA
+#define DMA_CNT_7 0xCE
+
+#define DMA_PAGE_0 0x87 /* DMA page registers */
+#define DMA_PAGE_1 0x83
+#define DMA_PAGE_2 0x81
+#define DMA_PAGE_3 0x82
+#define DMA_PAGE_5 0x8B
+#define DMA_PAGE_6 0x89
+#define DMA_PAGE_7 0x8A
+
+#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+ if (dmanr<=3)
+ dma_outb(dmanr, DMA1_MASK_REG);
+ else
+ dma_outb(dmanr & 3, DMA2_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+ if (dmanr<=3)
+ dma_outb(dmanr | 4, DMA1_MASK_REG);
+ else
+ dma_outb((dmanr & 3) | 4, DMA2_MASK_REG);
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+ if (dmanr<=3)
+ dma_outb(0, DMA1_CLEAR_FF_REG);
+ else
+ dma_outb(0, DMA2_CLEAR_FF_REG);
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+ if (dmanr<=3)
+ dma_outb(mode | dmanr, DMA1_MODE_REG);
+ else
+ dma_outb(mode | (dmanr&3), DMA2_MODE_REG);
+}
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+ switch(dmanr) {
+ case 0:
+ dma_outb(pagenr, DMA_PAGE_0);
+ break;
+ case 1:
+ dma_outb(pagenr, DMA_PAGE_1);
+ break;
+ case 2:
+ dma_outb(pagenr, DMA_PAGE_2);
+ break;
+ case 3:
+ dma_outb(pagenr, DMA_PAGE_3);
+ break;
+ case 5:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_5);
+ break;
+ case 6:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_6);
+ break;
+ case 7:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_7);
+ break;
+ }
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+ set_dma_page(dmanr, a>>16);
+ if (dmanr <= 3) {
+ dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ } else {
+ dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+ dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+ }
+}
+
+
+/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+ * a specific DMA channel.
+ * You must ensure the parameters are valid.
+ * NOTE: from a manual: "the number of transfers is one more
+ * than the initial word count"! This is taken into account.
+ * Assumes dma flip-flop is clear.
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ count--;
+ if (dmanr <= 3) {
+ dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ } else {
+ dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+ dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+ }
+}
+
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+ unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
+ : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
+
+ /* using short to get 16-bit wrap around */
+ unsigned short count;
+
+ count = 1 + dma_inb(io_port);
+ count += dma_inb(io_port) << 8;
+
+ return (dmanr<=3)? count : (count<<1);
+}
+
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr, char * deviceID); /* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr); /* release it again */
+
+
+#endif /* _ASM_MIPS_DMA_H */
diff --git a/include/asm-mips/head.h b/include/asm-mips/head.h
new file mode 100644
index 000000000..e0e01ec52
--- /dev/null
+++ b/include/asm-mips/head.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_MIPS_HEAD_H
+#define _ASM_MIPS_HEAD_H
+
+#include <linux/types.h>
+
+extern unsigned long swapper_pg_dir[1024];
+extern ulong IRQ_vectors[];
+
+#endif
diff --git a/include/asm-mips/in.h b/include/asm-mips/in.h
new file mode 100644
index 000000000..18074abb9
--- /dev/null
+++ b/include/asm-mips/in.h
@@ -0,0 +1,34 @@
+#ifndef _ASM_I386_IN_H
+#define _ASM_I386_IN_H
+
+static __inline__ unsigned long int
+__ntohl(unsigned long int x)
+{
+ return (((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24));
+}
+
+static __inline__ unsigned short int
+__ntohs(unsigned short int x)
+{
+ return (((x & 0x00ff) << 8) |
+ ((x & 0xff00) >> 8));
+}
+
+#define __htonl(x) __ntohl(x)
+#define __htons(x) __ntohs(x)
+
+#ifdef __OPTIMIZE__
+# define ntohl(x) \
+(__ntohl((x)))
+# define ntohs(x) \
+(__ntohs((x)))
+# define htonl(x) \
+(__htonl((x)))
+# define htons(x) \
+(__htons((x)))
+#endif
+
+#endif /* _ASM_I386_IN_H */
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
new file mode 100644
index 000000000..6450b1698
--- /dev/null
+++ b/include/asm-mips/interrupt.h
@@ -0,0 +1,40 @@
+#ifndef _ASM_MIPS_INTERRUPT_H
+#define _ASM_MIPS_INTERRUPT_H
+
+extern inline void mark_bh(int nr)
+{
+ __asm__ __volatile__(
+ "1:\tll\t$8,(%0)\n\t"
+ "or\t$8,$8,%1\n\t"
+ "sc\t$8,(%0)\n\t"
+ "beq\t$0,$8,1b\n\t"
+ : "=m" (bh_active)
+ : "r" (1<<nr)
+ : "$8","memory");
+}
+
+extern inline void disable_bh(int nr)
+{
+ __asm__ __volatile__(
+ "1:\tll\t$8,(%0)\n\t"
+ "and\t$8,$8,%1\n\t"
+ "sc\t$8,(%0)\n\t"
+ "beq\t$0,$8,1b\n\t"
+ : "=m" (bh_mask)
+ : "r" (1<<nr)
+ : "$8","memory");
+}
+
+extern inline void enable_bh(int nr)
+{
+ __asm__ __volatile__(
+ "1:\tll\t$8,(%0)\n\t"
+ "or\t$8,$8,%1\n\t"
+ "sc\t$8,(%0)\n\t"
+ "beq\t$0,$8,1b\n\t"
+ : "=m" (bh_mask)
+ : "r" (1<<nr)
+ : "$8","memory");
+}
+
+#endif /* _ASM_MIPS_INTERRUPT_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
new file mode 100644
index 000000000..16dbd1b46
--- /dev/null
+++ b/include/asm-mips/io.h
@@ -0,0 +1,240 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+
+/*
+ * This file contains the definitions for the MIPS counterpart of the
+ * x86 in/out instructions. This heap of macros and C results in much
+ * better code than the approach of doing it in plain C.
+ *
+ * Ralf
+ *
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
+/*
+ * Thanks to James van Artsdalen for a better timing-fix than
+ * the two short jumps: using outb's to a nonexistent port seems
+ * to guarantee better timings even on fast machines.
+ *
+ * On the other hand, I'd like to be sure of a non-existent port:
+ * I feel a bit unsafe about using 0x80 (should be safe, though)
+ *
+ * Linus
+ */
+
+#define __SLOW_DOWN_IO \
+ __asm__ __volatile__( \
+ "sb\t$0,0x80(%0)" \
+ : : "d" (PORT_BASE));
+
+#ifdef REALLY_SLOW_IO
+#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
+#else
+#define SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+/*
+ * Talk about misusing macros..
+ */
+
+#define __OUT1(s) \
+extern inline void __out##s(unsigned int value, unsigned int port) {
+
+#define __OUT2(m) \
+__asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
+
+#define __OUT(m,s) \
+__OUT1(s) __OUT2(m) : : "d" (value), "i" (0), "d" (PORT_BASE+port)); } \
+__OUT1(s##c) __OUT2(m) : : "d" (value), "i" (port), "d" (PORT_BASE)); } \
+__OUT1(s##_p) __OUT2(m) : : "d" (value), "i" (0), "d" (PORT_BASE+port)); \
+ SLOW_DOWN_IO; } \
+__OUT1(s##c_p) __OUT2(m) : : "d" (value), "i" (port), "d" (PORT_BASE)); \
+ SLOW_DOWN_IO; }
+
+#define __IN1(s) \
+extern inline unsigned int __in##s(unsigned int port) { unsigned int _v;
+
+#define __IN2(m) \
+__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\t"
+
+#define __IN(m,s) \
+__IN1(s) __IN2(m) STR(FILL_LDS) : "=d" (_v) : "i" (0), "d" (PORT_BASE+port)); return _v; } \
+__IN1(s##c) __IN2(m) STR(FILL_LDS) : "=d" (_v) : "i" (port), "d" (PORT_BASE)); return _v; } \
+__IN1(s##_p) __IN2(m) : "=d" (_v) : "i" (0), "d" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
+__IN1(s##c_p) __IN2(m) : "=d" (_v) : "i" (port), "d" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
+
+#define __INS1(s) \
+extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
+
+#define __INS2(m) \
+__asm__ __volatile__ ( \
+ ".set\tnoreorder\n\t" \
+ ".set\tnoat\n" \
+ "1:\tl" #m "u\t$1,%4(%5)\n\t" \
+ "subu\t%1,%1,1\n\t" \
+ "s" #m "\t$1,(%0)\n\t" \
+ "bne\t$0,%1,1b\n\t" \
+ "addiu\t%0,%0,%6\n\t" \
+ ".set\tat\n\t" \
+ ".set\treorder"
+
+#define __INS(m,s,i) \
+__INS1(s) __INS2(m) \
+ : "=d" (addr), "=d" (count) \
+ : "0" (addr), "1" (count), "i" (0), "d" (PORT_BASE+port), "I" (i) \
+ : "$1");} \
+__INS1(s##c) __INS2(m) \
+ : "=d" (addr), "=d" (count) \
+ : "0" (addr), "1" (count), "i" (port), "d" (PORT_BASE), "I" (i) \
+ : "$1");}
+
+#define __OUTS1(s) \
+extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) {
+
+#define __OUTS2(m) \
+__asm__ __volatile__ ( \
+ ".set\tnoreorder\n\t" \
+ ".set\tnoat\n" \
+ "1:\tl" #m "u\t$1,(%0)\n\t" \
+ "subu\t%1,%1,1\n\t" \
+ "s" #m "\t$1,%4(%5)\n\t" \
+ "bne\t$0,%1,1b\n\t" \
+ "addiu\t%0,%0,%6\n\t" \
+ ".set\tat\n\t" \
+ ".set\treorder"
+
+#define __OUTS(m,s,i) \
+__OUTS1(s) __OUTS2(m) \
+ : "=d" (addr), "=d" (count) \
+ : "0" (addr), "1" (count), "i" (0), "d" (PORT_BASE+port), "I" (i) \
+ : "$1");} \
+__OUTS1(s##c) __OUTS2(m) \
+ : "=d" (addr), "=d" (count) \
+ : "0" (addr), "1" (count), "i" (port), "d" (PORT_BASE), "I" (i) \
+ : "$1");}
+
+__IN(b,b)
+__IN(h,w)
+__IN(w,l)
+
+__OUT(b,b)
+__OUT(h,w)
+__OUT(w,l)
+
+__INS(b,b,1)
+__INS(h,w,2)
+__INS(w,l,4)
+
+__OUTS(b,b,1)
+__OUTS(h,w,2)
+__OUTS(w,l,4)
+
+/*
+ * Note that due to the way __builtin_constant_p() works, you
+ * - can't use it inside a inline function (it will never be true)
+ * - you don't have to worry about side effects within the __builtin..
+ */
+#define outb(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outbc((val),(port)) : \
+ __outb((val),(port)))
+
+#define inb(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inbc(port) : \
+ __inb(port))
+
+#define outb_p(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outbc_p((val),(port)) : \
+ __outb_p((val),(port)))
+
+#define inb_p(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inbc_p(port) : \
+ __inb_p(port))
+
+#define outw(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outwc((val),(port)) : \
+ __outw((val),(port)))
+
+#define inw(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inwc(port) : \
+ __inw(port))
+
+#define outw_p(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outwc_p((val),(port)) : \
+ __outw_p((val),(port)))
+
+#define inw_p(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inwc_p(port) : \
+ __inw_p(port))
+
+#define outl(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outlc((val),(port)) : \
+ __outl((val),(port)))
+
+#define inl(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inlc(port) : \
+ __inl(port))
+
+#define outl_p(val,port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outlc_p((val),(port)) : \
+ __outl_p((val),(port)))
+
+#define inl_p(port) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inlc_p(port) : \
+ __inl_p(port))
+
+
+#define outsb(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outsbc((port),(addr),(count)) : \
+ __outsb ((port),(addr),(count)))
+
+#define insb(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __insbc((port),(addr),(count)) : \
+ __insb((port),(addr),(count)))
+
+#define outsw(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outswc((port),(addr),(count)) : \
+ __outsw ((port),(addr),(count)))
+
+#define insw(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inswc((port),(addr),(count)) : \
+ __insw((port),(addr),(count)))
+
+#define outsl(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __outslc((port),(addr),(count)) : \
+ __outsl ((port),(addr),(count)))
+
+#define insl(port,addr,count) \
+((__builtin_constant_p((port)) && (port) < 32768) ? \
+ __inslc((port),(addr),(count)) : \
+ __insl((port),(addr),(count)))
+
+#endif
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
new file mode 100644
index 000000000..a6d10c29e
--- /dev/null
+++ b/include/asm-mips/irq.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-mips/irq.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 by Waldorf GMBH
+ * written by Ralf Baechle
+ *
+ */
+#ifndef _ASM_MIPS_IRQ_H
+#define _ASM_MIPS_IRQ_H
+
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
+#endif /* _ASM_MIPS_IRQ_H */
diff --git a/include/asm-mips/mipsconfig.h b/include/asm-mips/mipsconfig.h
new file mode 100644
index 000000000..4194df998
--- /dev/null
+++ b/include/asm-mips/mipsconfig.h
@@ -0,0 +1,29 @@
+/*
+ * linux/include/asm-mips/mipsconfig.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 by Waldorf GMBH
+ * written by Ralf Baechle
+ *
+ */
+#ifndef _ASM_MIPS_MIPS_CONFIG_H
+#define _ASM_MIPS_MIPS_CONFIG_H
+
+/*
+ * This is the virtual adress to which all ports are being mapped.
+ */
+#define PORT_BASE 0xe0000000
+#define PORT_BASE_HIGH 0xe000
+
+#define NUMBER_OF_TLB_ENTRIES 48
+
+/*
+ * Absolute address of the kernelstack is 0x80000280
+ */
+#define KERNEL_SP_HIGH 0x8000
+#define KERNEL_SP_LOW 0x0280
+
+#endif /* _ASM_MIPS_MIPS_CONFIG_H */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 2fd47473e..b9b96e73d 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -24,6 +24,19 @@
#endif
/*
+ * On the R2000/3000 load instructions are not interlocked -
+ * we therefore sometimes need to fill load delay slots with nop
+ * which are not needed for >=R4000.
+ *
+ * FIXME: Don't know about R6000
+ */
+#if !defined (__R4000__)
+#define FILL_LDS nop
+#else
+#define FILL_LDS
+#endif
+
+/*
* Coprocessor 0 register names
*/
#define CP0_INDEX $0
@@ -53,15 +66,15 @@
#define CP0_ERROREPC $30
/*
- * Values for pagemask register
+ * Values for PageMask register
*/
-#define PM_4K 0x000000000
-#define PM_16K 0x000060000
-#define PM_64K 0x0001e0000
-#define PM_256K 0x0007e0000
-#define PM_1M 0x001fe0000
-#define PM_4M 0x007fe0000
-#define PM_16M 0x01ffe0000
+#define PM_4K 0x00000000
+#define PM_16K 0x00006000
+#define PM_64K 0x0001e000
+#define PM_256K 0x0007e000
+#define PM_1M 0x001fe000
+#define PM_4M 0x007fe000
+#define PM_16M 0x01ffe000
/*
* Values used for computation of new tlb entries
@@ -80,4 +93,86 @@
#define VPN(addr,pagesizeshift) ((addr) & ~((1 << (pagesizeshift))-1))
#define PFN(addr,pagesizeshift) (((addr) & ((1 << (pagesizeshift))-1)) << 6)
+/*
+ * Macros to access the system control copprocessor
+ */
+#define read_32bit_cp0_register(source) \
+({ int __res; \
+ __asm__ __volatile__( \
+ "mfc0\t%0,"STR(source) \
+ : "=r" (__res)); \
+ __res;})
+
+#define read_64bit_cp0_register(target,source) \
+ __asm__ __volatile__( \
+ ".set\tnoat\n\t" \
+ "dmfc0\t$1,"STR(source)"\n\t" \
+ "sd\t$1,(%0)\n\t" \
+ ".set\tat" \
+ : \
+ : "r" (target) \
+ : "$1","memory");
+
+
+#define write_32bit_cp0_register(register,value) \
+ __asm__ __volatile__( \
+ "mtc0\t%0,"STR(register) \
+ : : "r" (value));
+
+/*
+ * Inline code for use of the ll and sc instructions
+ *
+ * FIXME: This code code will break on R[23]00 CPUs
+ * Since these operations are only being used for atomic operations
+ * the easiest workaround for the R[23]00 is to disable interrupts.
+ */
+#define load_linked(addr) \
+({ \
+ unsigned int __res; \
+ \
+ __asm__ __volatile__( \
+ "ll\t%0,(%1)" \
+ : "=r" (__res) \
+ : "r" ((unsigned int) (addr))); \
+ \
+ __res; \
+})
+
+#define store_conditional(value,addr) \
+({ \
+ int __res; \
+ \
+ __asm__ __volatile__( \
+ "sc\t%0,(%2)" \
+ : "=r" (__res) \
+ : "0" (value), "r" (addr)); \
+ \
+ __res; \
+})
+
+/*
+ * Bitfields in the cp0 status register
+ *
+ * Refer to MIPS R4600 manual, page 5-4 for explanation
+ */
+#define ST0_IE (1 << 1)
+#define ST0_EXL (1 << 2)
+#define ST0_ERL (3 << 3)
+#define ST0_UX (1 << 5)
+#define ST0_SX (1 << 6)
+#define ST0_KX (1 << 7)
+#define ST0_IM (255 << 8)
+#define ST0_DE (1 << 16)
+#define ST0_CE (1 << 17)
+#define ST0_CH (1 << 18)
+#define ST0_SR (1 << 20)
+#define ST0_BEV (1 << 22)
+#define ST0_RE (1 << 25)
+#define ST0_FR (1 << 26)
+#define ST0_CU (15 << 28)
+#define ST0_CU0 (1 << 28)
+#define ST0_CU1 (1 << 29)
+#define ST0_CU2 (1 << 30)
+#define ST0_CU3 (1 << 31)
+
#endif /* _ASM_MIPS_MIPSREGS_H_ */
diff --git a/include/asm-mips/mm.h b/include/asm-mips/mm.h
new file mode 100644
index 000000000..84a09e1c8
--- /dev/null
+++ b/include/asm-mips/mm.h
@@ -0,0 +1,94 @@
+#ifndef _ASM_MIPS_MM_H_
+#define _ASM_MIPS_MM_H_
+
+#if defined (__KERNEL__)
+
+/*
+ * Note that we shift the lower 32bits of each EntryLo[01] entry
+ * 6 bit to the left. That way we can convert the PFN into the
+ * physical address by a single and operation and gain 6 aditional
+ * bits for storing information which isn't present in a normal
+ * MIPS page table.
+ * I've also changed the naming of some bits so that they conform
+ * the i386 naming as much as possible.
+ */
+#define PAGE_COW (1<<0) /* implemented in software */
+#define PAGE_ACCESSED (1<<1) /* implemented in software */
+#define PAGE_DIRTY (1<<2) /* implemented in software */
+#define PAGE_USER (1<<3) /* implemented in software */
+#define PAGE_UNUSED2 (1<<4) /* for use by software */
+#define PAGE_UNUSED3 (1<<5) /* for use by software */
+#define PAGE_GLOBAL (1<<6)
+#define PAGE_VALID (1<<7)
+/*
+ * In the hardware the PAGE_WP bit is represented by the dirty bit
+ */
+#define PAGE_RW (1<<8)
+#define CACHE_CACHABLE_NO_WA (0<<9)
+#define CACHE_CACHABLE_WA (1<<9)
+#define CACHE_UNCACHED (2<<9)
+#define CACHE_CACHABLE_NONCOHERENT (3<<9)
+#define CACHE_CACHABLE_CE (4<<9)
+#define CACHE_CACHABLE_COW (5<<9)
+#define CACHE_CACHABLE_CUW (6<<9)
+#define CACHE_MASK (7<<9)
+
+#define PAGE_PRIVATE (PAGE_VALID | PAGE_ACCESSED | PAGE_DIRTY | \
+ PAGE_RW | PAGE_COW)
+#define PAGE_SHARED (PAGE_VALID | PAGE_ACCESSED | PAGE_DIRTY | PAGE_RW)
+#define PAGE_COPY (PAGE_VALID | PAGE_ACCESSED | PAGE_COW)
+#define PAGE_READONLY (PAGE_VALID | PAGE_ACCESSED)
+#define PAGE_TABLE (PAGE_VALID | PAGE_ACCESSED | PAGE_DIRTY | PAGE_RW)
+
+/*
+ * Predicate for testing
+ */
+#define IS_PAGE_USER(p) (((unsigned long)(p)) & PAGE_USER)
+
+extern inline long find_in_swap_cache (unsigned long addr)
+{
+ unsigned long entry;
+
+#ifdef SWAP_CACHE_INFO
+ swap_cache_find_total++;
+#endif
+ cli();
+ entry = swap_cache[addr >> PAGE_SHIFT];
+ swap_cache[addr >> PAGE_SHIFT] = 0;
+ sti();
+#ifdef SWAP_CACHE_INFO
+ if (entry)
+ swap_cache_find_success++;
+#endif
+ return entry;
+}
+
+extern inline int delete_from_swap_cache(unsigned long addr)
+{
+ unsigned long entry;
+
+#ifdef SWAP_CACHE_INFO
+ swap_cache_del_total++;
+#endif
+ cli();
+ entry = swap_cache[addr >> PAGE_SHIFT];
+ swap_cache[addr >> PAGE_SHIFT] = 0;
+ sti();
+ if (entry) {
+#ifdef SWAP_CACHE_INFO
+ swap_cache_del_success++;
+#endif
+ swap_free(entry);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * memory.c & swap.c
+ */
+extern void mem_init(unsigned long start_mem, unsigned long end_mem);
+
+#endif /* defined (__KERNEL__) */
+
+#endif /* _ASM_MIPS_MM_H_ */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
new file mode 100644
index 000000000..0176c0251
--- /dev/null
+++ b/include/asm-mips/page.h
@@ -0,0 +1,90 @@
+#ifndef _ASM_MIPS_LINUX_PAGE_H
+#define _ASM_MIPS_LINUX_PAGE_H
+
+/*
+ * For now...
+ */
+#define invalidate()
+
+ /* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT 12
+#define PGDIR_SHIFT 22
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+
+#ifdef __KERNEL__
+
+ /* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR (8*sizeof(unsigned long))
+ /* to mask away the intra-page address bits */
+#define PAGE_MASK (~(PAGE_SIZE-1))
+ /* to mask away the intra-page address bits */
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+ /* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+ /* to align the pointer to a pointer address */
+#define PTR_MASK (~(sizeof(void*)-1))
+
+ /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+ /* 64-bit machines, beware! SRB. */
+#define SIZEOF_PTR_LOG2 2
+
+ /* to find an entry in a page-table-directory */
+#define PAGE_DIR_OFFSET(base,address) ((unsigned long*)((base)+\
+ ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)*2&PTR_MASK&~PAGE_MASK)))
+ /* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+ ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+ /* the no. of pointers that fit on a page */
+#define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*))
+
+#define copy_page(from,to) \
+ __copy_page((void *)(from),(void *)(to), PAGE_SIZE)
+
+#if defined (__R4000__)
+/*
+ * Do it the 64bit way...
+ */
+extern __inline__ void __copy_page(void *from, void *to, int bytes)
+{
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+ "1:\tld\t$1,(%0)\n\t"
+ "addiu\t%0,%0,8\n\t"
+ "sd\t$1,(%1)\n\t"
+ "subu\t%2,%2,8\n\t"
+ "bne\t$0,%2,1b\n\t"
+ "addiu\t%1,%1,8\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n\t"
+ : "=r" (from), "=r" (to), "=r" (bytes)
+ : "r" (from), "r" (to), "r" (bytes)
+ : "$1");
+}
+#else
+/*
+ * Use 32 bit Diesel fuel...
+ */
+extern __inline__ void __copy_page(void *from, void *to, int bytes)
+{
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+ "1:\tlw\t$1,(%0)\n\t"
+ "addiu\t%0,%0,4\n\t"
+ "sw\t$1,(%1)\n\t"
+ "subu\t%2,%2,4\n\t"
+ "bne\t$0,%2,1b\n\t"
+ "addiu\t%1,%1,4\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n\t"
+ : "=r" (from), "=r" (to), "=r" (bytes)
+ : "r" (from), "r" (to), "r" (bytes)
+ : "$1");
+}
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MIPS_LINUX_PAGE_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
new file mode 100644
index 000000000..97b08ce74
--- /dev/null
+++ b/include/asm-mips/ptrace.h
@@ -0,0 +1,110 @@
+/*
+ * linux/include/asm-mips/ptrace.h
+ *
+ * machine dependend structs and defines to help the user use
+ * the ptrace system call.
+ */
+#ifndef _ASM_MIPS_PTRACE_H
+#define _ASM_MIPS_PTRACE_H
+
+/*
+ * use ptrace (3 or 6, pid, PT_EXCL, data); to read or write
+ * the processes registers.
+ *
+ * This defines/structures corrospond to the register layout on stack -
+ * if the order here is changed, it needs to be updated in
+ * arch/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
+ * asm-mips/ptrace.c, include/asm-mips/ptrace.h.
+ */
+
+#define IN_REG1 0
+#define IN_REG2 1
+#define IN_REG3 2
+#define IN_REG4 3
+#define IN_REG5 4
+#define IN_REG6 5
+#define IN_REG7 6
+#define IN_REG8 7
+#define IN_REG9 8
+#define IN_REG10 9
+#define IN_REG11 10
+#define IN_REG12 11
+#define IN_REG13 12
+#define IN_REG14 13
+#define IN_REG15 14
+#define IN_REG16 15
+#define IN_REG17 16
+#define IN_REG18 17
+#define IN_REG19 18
+#define IN_REG20 19
+#define IN_REG21 20
+#define IN_REG22 21
+#define IN_REG23 22
+#define IN_REG24 23
+#define IN_REG25 24
+
+/*
+ * k0 and k1 not saved
+ */
+#define IN_REG28 25
+#define IN_REG29 26
+#define IN_REG30 27
+#define IN_REG31 28
+
+/*
+ * Saved special registers
+ */
+#define FR_LO ((IN_REG31) + 1)
+#define FR_HI ((IN_LO) + 1)
+
+/*
+ * Saved cp0 registers
+ */
+#define IN_CP0_STATUS ((IN_LO) + 1)
+#define IN_CP0_EPC ((IN_CP0_STATUS) + 1)
+#define IN_CP0_ERROREPC ((IN_CP0_EPC) + 1)
+
+/*
+ * Some goodies...
+ */
+#define IN_INTERRUPT ((IN_CP0_ERROREPC) + 1)
+#define IN_ORIG_REG2 ((IN_INTERRUPT) + 1)
+
+/*
+ * this struct defines the way the registers are stored on the
+ * stack during a system call/exception. As usual the registers
+ * k0/k1 aren't being saved.
+ */
+
+struct pt_regs {
+ /*
+ * saved main processor registers
+ */
+ long reg1, reg2, reg3, reg4, reg5, reg6, reg7;
+ long reg8, reg9, reg10, reg11, reg12, reg13, reg14, reg15;
+ long reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+ long reg24, reg25, reg28, reg29, reg30, reg31;
+ /*
+ * Saved special registers
+ */
+ long lo;
+ long hi;
+ /*
+ * saved cp0 registers
+ */
+ unsigned long cp0_status;
+ unsigned long cp0_epc;
+ unsigned long cp0_errorepc;
+ /*
+ * Some goodies...
+ */
+ unsigned long interrupt;
+ long orig_reg2;
+};
+
+/*
+ * This function computes the interrupt number from the stack frame
+ */
+#define pt_regs2irq(p) ((int) ((struct pt_regs *)p)->interrupt)
+
+#endif /* _ASM_MIPS_PTRACE_H */
diff --git a/include/asm-mips/regdef.h b/include/asm-mips/regdef.h
new file mode 100644
index 000000000..1fbe8f19f
--- /dev/null
+++ b/include/asm-mips/regdef.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-mips/regdefs.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 by Ralf Baechle
+ */
+
+#ifndef _ASM_MIPS_REGSDEFS_H_
+#define _ASM_MIPS_REGSDEFS_H_
+
+/*
+ * Symbolic register names
+ */
+#define zero $0 /* wired zero */
+#define AT $1 /* assembler temp (uprcase, because ".set at") */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* caller saved */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define s0 $16 /* callee saved */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24 /* caller saved */
+#define t9 $25
+#define k0 $26 /* kernel scratch */
+#define k1 $27
+#define gp $28 /* global pointer */
+#define sp $29 /* stack pointer */
+#define fp $30 /* frame pointer */
+#define ra $31 /* return address */
+
+#endif /* _ASM_MIPS_REGSDEFS_H_ */
diff --git a/include/asm-mips/sched.h b/include/asm-mips/sched.h
new file mode 100644
index 000000000..661675a37
--- /dev/null
+++ b/include/asm-mips/sched.h
@@ -0,0 +1,240 @@
+#ifndef _ASM_MIPS_SCHED_H
+#define _ASM_MIPS_SCHED_H
+
+#include <asm/system.h>
+
+/*
+ * System setup and hardware bug flags..
+ */
+extern int hard_math;
+extern int wp_works_ok; /* doesn't work on a 386 */
+
+extern unsigned long intr_count;
+extern unsigned long event;
+
+#define start_bh_atomic() \
+{int flags; save_flags(flags); cli(); intr_count++; restore_flags(flags)}
+
+#define end_bh_atomic() \
+{int flags; save_flags(flags); cli(); intr_count--; restore_flags(flags)}
+
+/*
+ * Bus types (default is ISA, but people can check others with these..)
+ * MCA_bus hardcoded to 0 for now.
+ */
+extern int EISA_bus;
+#define MCA_bus 0
+
+/*
+ * User space process size: 2GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+#define TASK_SIZE 0x80000000
+
+#define NUM_FPA_REGS 32
+
+struct mips_fpa_hard_struct {
+ float fp_regs[NUM_FPA_REGS];
+ unsigned int control;
+};
+
+struct mips_fpa_soft_struct {
+ /*
+ * FIXME: no fpa emulator yet, but who cares?
+ */
+ long dummy;
+ };
+
+union mips_fpa_union {
+ struct mips_fpa_hard_struct hard;
+ struct mips_fpa_soft_struct soft;
+};
+
+#define INIT_FPA { \
+ 0, \
+}
+
+struct tss_struct {
+ /*
+ * saved main processor registers
+ */
+ unsigned long reg1, reg2, reg3, reg4, reg5, reg6, reg7;
+ unsigned long reg8, reg9, reg10, reg11, reg12, reg13, reg14, reg15;
+ unsigned long reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+ unsigned long reg24, reg25, reg26, reg29, reg30, reg31;
+ /*
+ * saved cp0 registers
+ */
+ unsigned int cp0_status;
+ unsigned long cp0_epc;
+ unsigned long cp0_errorepc;
+ unsigned long cp0_context;
+ /*
+ * saved fpa/fpa emulator stuff
+ */
+ union mips_fpa_union fpa;
+ /*
+ * Other stuff associated with the process
+ */
+ unsigned long cp0_badvaddr;
+ unsigned long errorcode;
+ unsigned long trap_no;
+ unsigned long fs; /* "Segment" pointer */
+ unsigned long ksp; /* Kernel stack pointer */
+ unsigned long pg_dir; /* L1 page table pointer */
+};
+
+#define INIT_TSS { \
+ /* \
+ * saved main processor registers \
+ */ \
+ 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, \
+ /* \
+ * saved cp0 registers \
+ */ \
+ 0, 0, 0, 0, \
+ /* \
+ * saved fpa/fpa emulator stuff \
+ */ \
+ INIT_FPA, \
+ /* \
+ * Other stuff associated with the process\
+ */ \
+ 0, 0, 0, KERNEL_DS, 0, 0 \
+}
+
+struct task_struct {
+ /*
+ * these are hardcoded - don't touch
+ */
+ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
+ long counter;
+ long priority;
+ unsigned long signal;
+ unsigned long blocked; /* bitmap of masked signals */
+ unsigned long flags; /* per process flags, defined below */
+ int errno;
+ int debugreg[8]; /* Hardware debugging registers */
+ struct exec_domain *exec_domain;
+ /*
+ * various fields
+ */
+ struct linux_binfmt *binfmt;
+ struct task_struct *next_task, *prev_task;
+ struct sigaction sigaction[32];
+ unsigned long saved_kernel_stack;
+ unsigned long kernel_stack_page;
+ int exit_code, exit_signal;
+ unsigned long personality;
+ int dumpable:1;
+ int did_exec:1;
+ int pid,pgrp,session,leader;
+ int groups[NGROUPS];
+ /*
+ * pointers to (original) parent process, youngest child, younger
+ * sibling, older sibling, respectively. (p->father can be replaced
+ * with p->p_pptr->pid)
+ */
+ struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ struct wait_queue *wait_chldexit; /* for wait4() */
+ unsigned short uid,euid,suid,fsuid;
+ unsigned short gid,egid,sgid,fsgid;
+ unsigned long timeout;
+ unsigned long it_real_value, it_prof_value, it_virt_value;
+ unsigned long it_real_incr, it_prof_incr, it_virt_incr;
+ long utime, stime, cutime, cstime, start_time;
+ struct rlimit rlim[RLIM_NLIMITS];
+ unsigned short used_math;
+ char comm[16];
+ /*
+ * virtual 86 mode stuff
+ */
+ struct vm86_struct * vm86_info;
+ unsigned long screen_bitmap;
+ unsigned long v86flags, v86mask, v86mode;
+ /*
+ * file system info
+ */
+ int link_count;
+ struct tty_struct *tty; /* NULL if no tty */
+ /*
+ * ipc stuff
+ */
+ struct sem_undo *semundo;
+ /*
+ * ldt for this task - used by Wine. If NULL, default_ldt is used
+ */
+ struct desc_struct *ldt;
+ /*
+ * tss for this task
+ */
+ struct tss_struct tss;
+ /*
+ * filesystem information
+ */
+ struct fs_struct fs[1];
+ /*
+ * open file information
+ */
+ struct files_struct files[1];
+ /*
+ * memory management info
+ */
+ struct mm_struct mm[1];
+};
+
+/*
+ * INIT_TASK is used to set up the first task table, touch at
+ * your own risk!. Base=0, limit=0x1fffff (=2MB)
+ */
+#define INIT_TASK \
+/* state etc */ { 0,15,15,0,0,0,0, \
+/* debugregs */ { 0, }, \
+/* exec domain */&default_exec_domain, \
+/* binfmt */ NULL, \
+/* schedlink */ &init_task,&init_task, \
+/* signals */ {{ 0, },}, \
+/* stack */ 0,(unsigned long) &init_kernel_stack, \
+/* ec,brk... */ 0,0,0,0,0, \
+/* pid etc.. */ 0,0,0,0, \
+/* suppl grps*/ {NOGROUP,}, \
+/* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \
+/* uid etc */ 0,0,0,0,0,0,0,0, \
+/* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
+/* rlimits */ { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \
+ {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \
+ { 0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
+/* math */ 0, \
+/* comm */ "swapper", \
+/* vm86_info */ NULL, 0, 0, 0, 0, \
+/* fs info */ 0,NULL, \
+/* ipc */ NULL, \
+/* ldt */ NULL, \
+/* tss */ INIT_TSS, \
+/* fs */ { INIT_FS }, \
+/* files */ { INIT_FILES }, \
+/* mm */ { INIT_MM } \
+}
+
+#ifdef __KERNEL__
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ * This also clears the TS-flag if the task we switched to has used
+ * tha math co-processor latest.
+ */
+#define switch_to(tsk) \
+ __asm__(""::); /* fix me */
+
+/*
+ * Does the process account for user or for system time?
+ */
+#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x18))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MIPS_SCHED_H */
diff --git a/include/asm-mips/segment.h b/include/asm-mips/segment.h
index 8b29ad0b2..511c499c8 100644
--- a/include/asm-mips/segment.h
+++ b/include/asm-mips/segment.h
@@ -12,11 +12,19 @@
#ifndef _ASM_MIPS_SEGMENT_H_
#define _ASM_MIPS_SEGMENT_H_
+#define KERNEL_CS 0x80000000
+#define KERNEL_DS KERNEL_CS
+
+#define USER_CS 0x00000000
+#define USER_DS USER_CS
+
+#ifndef __ASSEMBLY__
+
static inline unsigned char get_user_byte(const char * addr)
{
- register unsigned char _v;
+ unsigned char _v;
- __asm__ ("lbu\t%0,%1":"=r" (_v):"r" (*addr));
+ __asm__ ("lbu\t%0,(%1)":"=r" (_v):"r" (*addr));
return _v;
}
@@ -27,7 +35,7 @@ static inline unsigned short get_user_word(const short *addr)
{
unsigned short _v;
- __asm__ ("lhu\t%0,%1":"=r" (_v):"r" (*addr));
+ __asm__ ("lhu\t%0,(%1)":"=r" (_v):"r" (*addr));
return _v;
}
@@ -38,7 +46,7 @@ static inline unsigned long get_user_long(const int *addr)
{
unsigned long _v;
- __asm__ ("lwu\t%0,%1":"=r" (_v):"r" (*addr)); \
+ __asm__ ("lwu\t%0,(%1)":"=r" (_v):"r" (*addr)); \
return _v;
}
@@ -48,7 +56,7 @@ static inline unsigned long get_user_dlong(const int *addr)
{
unsigned long _v;
- __asm__ ("ld\t%0,%1":"=r" (_v):"r" (*addr)); \
+ __asm__ ("ld\t%0,(%1)":"=r" (_v):"r" (*addr)); \
return _v;
}
@@ -56,28 +64,28 @@ static inline unsigned long get_user_dlong(const int *addr)
static inline void put_user_byte(char val,char *addr)
{
-__asm__ ("sb\t%0,%1": /* no outputs */ :"r" (val),"r" (*addr));
+__asm__ ("sb\t%0,(%1)": /* no outputs */ :"r" (val),"r" (*addr));
}
#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
static inline void put_user_word(short val,short * addr)
{
-__asm__ ("sh\t%0,%1": /* no outputs */ :"r" (val),"r" (*addr));
+__asm__ ("sh\t%0,(%1)": /* no outputs */ :"r" (val),"r" (*addr));
}
#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
static inline void put_user_long(unsigned long val,int * addr)
{
-__asm__ ("sw\t%0,%1": /* no outputs */ :"r" (val),"r" (*addr));
+__asm__ ("sw\t%0,(%1)": /* no outputs */ :"r" (val),"r" (*addr));
}
#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
static inline void put_user_dlong(unsigned long val,int * addr)
{
-__asm__ ("sd\t%0,%1": /* no outputs */ :"r" (val),"r" (*addr));
+__asm__ ("sd\t%0,(%1)": /* no outputs */ :"r" (val),"r" (*addr));
}
#define put_fs_dlong(x,addr) put_user_dlong((x),(int *)(addr))
@@ -214,4 +222,6 @@ static inline void set_fs(unsigned long val)
segment_fs = val;
}
+#endif
+
#endif /* _ASM_MIPS_SEGMENT_H_ */
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
new file mode 100644
index 000000000..6c66d6271
--- /dev/null
+++ b/include/asm-mips/signal.h
@@ -0,0 +1,28 @@
+#ifndef _ASM_MIPS_SIGNAL_H
+#define _ASM_MIPS_SIGNAL_H
+
+#ifdef __KERNEL__
+
+struct sigcontext_struct {
+ /*
+ * In opposite to the SVr4 implentation in Risc/OS the
+ * sc_ra points to an address suitable to "jr ra" to.
+ * Registers that are callee saved by convention aren't
+ * being saved on entry of a signal handler.
+ */
+ unsigned long sc_at;
+ unsigned long sc_v0, sc_v1;
+ unsigned long sc_a0, sc_a1, sc_a2, sc_a3;
+ unsigned long sc_t0, sc_t1, sc_t2, sc_t3, sc_t4;
+ unsigned long sc_t5, sc_t6, sc_t7, sc_t8, sc_t9;
+ /*
+ * Old userstack pointer ($29)
+ */
+ unsigned long sc_sp;
+
+ unsigned long oldmask;
+};
+
+#endif
+
+#endif /* _ASM_MIPS_SIGNAL_H */
diff --git a/include/asm-mips/slots.h b/include/asm-mips/slots.h
new file mode 100644
index 000000000..fa5ae9fcb
--- /dev/null
+++ b/include/asm-mips/slots.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-mips/slots.h
+ *
+ * Written by Ralf Baechle
+ * Copyright (C) 1994 by Waldorf GMBH
+ */
+#ifndef _ASM_MIPS_SLOTS_H
+#define _ASM_MIPS_SLOTS_H
+
+/*
+ * SLOTSPACE is the address to which the physical address 0
+ * of the Slotspace is mapped by the chipset in the main CPU's
+ * address space.
+ */
+#define SLOTSPACE 0xe1000000
+
+#endif /* _ASM_MIPS_SLOTS_H */
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
new file mode 100644
index 000000000..0c3c4699c
--- /dev/null
+++ b/include/asm-mips/stackframe.h
@@ -0,0 +1,176 @@
+/*
+ * include/asm-mips/stackframe.h
+ *
+ * Copyright (C) 1994 Waldorf GMBH
+ * written by Ralf Baechle
+ */
+
+#ifndef _ASM_MIPS_STACKFRAME_H_
+#define _ASM_MIPS_STACKFRAME_H_
+
+/*
+ * Stack layout for all exceptions:
+ *
+ * ptrace needs to have all regs on the stack.
+ * if the order here is changed, it needs to be
+ * updated in asm/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
+ * asm-mips/ptrace.c, include/asm-mips/ptrace.h
+ * and asm-mips/ptrace
+ */
+
+/*
+ * Offsets into the Interrupt stackframe.
+ */
+#define FR_REG1 0
+#define FR_REG2 4
+#define FR_REG3 8
+#define FR_REG4 12
+#define FR_REG5 16
+#define FR_REG6 20
+#define FR_REG7 24
+#define FR_REG8 28
+#define FR_REG9 32
+#define FR_REG10 36
+#define FR_REG11 40
+#define FR_REG12 44
+#define FR_REG13 48
+#define FR_REG14 52
+#define FR_REG15 56
+#define FR_REG16 60
+#define FR_REG17 64
+#define FR_REG18 68
+#define FR_REG19 72
+#define FR_REG20 76
+#define FR_REG21 80
+#define FR_REG22 84
+#define FR_REG23 88
+#define FR_REG24 92
+#define FR_REG25 96
+
+/*
+ * $26 (k0) and $27 (k1) not saved
+ */
+#define FR_REG28 100
+#define FR_REG29 104
+#define FR_REG30 108
+#define FR_REG31 112
+
+/*
+ * Saved special registers
+ */
+#define FR_LO ((FR_REG31) + 4)
+#define FR_HI ((FR_LO) + 4)
+
+/*
+ * Saved cp0 registers follow
+ */
+#define FR_STATUS ((FR_HI) + 4)
+#define FR_EPC ((FR_STATUS) + 4)
+#define FR_ERROREPC ((FR_EPC) + 4)
+
+/*
+ * Some goodies...
+ */
+#define FR_INTERRUPT ((FR_ERROREPC) + 4)
+#define FR_ORIG_REG2 ((FR_INTERRUPT) + 4)
+
+/*
+ * Size of stack frame
+ */
+#define FR_SIZE ((FR_ORIG_REG2) + 4)
+
+#define SAVE_ALL \
+ mfc0 k0,CP0_STATUS; \
+ andi k0,k0,0x18; /* extract KSU bits */ \
+ beq zero,k0,1f; \
+ move k1,sp; \
+ /* \
+ * Called from user mode, new stack \
+ */ \
+ lw k1,_kernelsp; \
+1: move k0,sp; \
+ subu sp,k1,FR_SIZE; \
+ sw k0,FR_REG29(sp); \
+ sw $2,FR_REG2(sp); \
+ sw $2,FR_ORIG_REG2(sp); \
+ mfc0 v0,CP0_STATUS; \
+ sw v0,FR_STATUS(sp); \
+ mfc0 v0,CP0_EPC; \
+ sw v0,FR_EPC(sp); \
+ mfc0 v0,CP0_ERROREPC; \
+ sw v0,FR_ERROREPC(sp); \
+ mfhi v0; \
+ sw v0,FR_HI(sp); \
+ mflo v0; \
+ sw v0,FR_LO(sp); \
+ sw $1,FR_REG1(sp); \
+ sw $3,FR_REG3(sp); \
+ sw $4,FR_REG4(sp); \
+ sw $5,FR_REG5(sp); \
+ sw $6,FR_REG6(sp); \
+ sw $7,FR_REG7(sp); \
+ sw $8,FR_REG8(sp); \
+ sw $9,FR_REG9(sp); \
+ sw $10,FR_REG10(sp); \
+ sw $11,FR_REG11(sp); \
+ sw $12,FR_REG12(sp); \
+ sw $13,FR_REG13(sp); \
+ sw $14,FR_REG14(sp); \
+ sw $15,FR_REG15(sp); \
+ sw $16,FR_REG16(sp); \
+ sw $17,FR_REG17(sp); \
+ sw $18,FR_REG18(sp); \
+ sw $19,FR_REG19(sp); \
+ sw $20,FR_REG20(sp); \
+ sw $21,FR_REG21(sp); \
+ sw $22,FR_REG22(sp); \
+ sw $23,FR_REG23(sp); \
+ sw $24,FR_REG24(sp); \
+ sw $25,FR_REG25(sp); \
+ sw $28,FR_REG28(sp); \
+ sw $30,FR_REG30(sp); \
+ sw $31,FR_REG31(sp)
+
+#define RESTORE_ALL \
+ lw v0,FR_ERROREPC(sp); \
+ lw v1,FR_EPC(sp); \
+ mtc0 v0,CP0_ERROREPC; \
+ lw v0,FR_HI(sp); \
+ mtc0 v1,CP0_EPC; \
+ lw v1,FR_LO(sp); \
+ mthi v0; \
+ lw v0,FR_STATUS(sp); \
+ mtlo v1; \
+ mtc0 v0,CP0_STATUS; \
+ lw $31,FR_REG31(sp); \
+ lw $30,FR_REG30(sp); \
+ lw $28,FR_REG28(sp); \
+ lw $25,FR_REG25(sp); \
+ lw $24,FR_REG24(sp); \
+ lw $23,FR_REG23(sp); \
+ lw $22,FR_REG22(sp); \
+ lw $21,FR_REG21(sp); \
+ lw $20,FR_REG20(sp); \
+ lw $19,FR_REG19(sp); \
+ lw $18,FR_REG18(sp); \
+ lw $17,FR_REG17(sp); \
+ lw $16,FR_REG16(sp); \
+ lw $15,FR_REG15(sp); \
+ lw $14,FR_REG14(sp); \
+ lw $13,FR_REG13(sp); \
+ lw $12,FR_REG12(sp); \
+ lw $11,FR_REG11(sp); \
+ lw $10,FR_REG10(sp); \
+ lw $9,FR_REG9(sp); \
+ lw $8,FR_REG8(sp); \
+ lw $7,FR_REG7(sp); \
+ lw $6,FR_REG6(sp); \
+ lw $5,FR_REG5(sp); \
+ lw $4,FR_REG4(sp); \
+ lw $3,FR_REG3(sp); \
+ lw $2,FR_REG2(sp); \
+ lw $1,FR_REG1(sp); \
+ lw sp,FR_REG29(sp); /* Deallocate stack */ \
+ eret
+
+#endif /* _ASM_MIPS_STACKFRAME_H_ */
diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h
index 06d4f2ce5..0116fd026 100644
--- a/include/asm-mips/string.h
+++ b/include/asm-mips/string.h
@@ -11,6 +11,8 @@
#ifndef _ASM_MIPS_STRING_H_
#define _ASM_MIPS_STRING_H_
+#include <asm/mipsregs.h>
+
#define __USE_PORTABLE_STRINGS_H_
extern inline char * strcpy(char * dest,const char *src)
@@ -77,7 +79,8 @@ extern inline int strcmp(const char * cs,const char * ct)
"bne\t$1,%2,2f\n\t"
"addiu\t%1,%1,1\n\t"
"bne\t$0,%2,1b\n\t"
- "lbu\t%2,(%0)\n"
+ "lbu\t%2,(%0)\n\t"
+ STR(FILL_LDS) "\n\t"
"move\t%2,$1\n"
"2:\tsub\t%2,%2,$1\n"
"3:\t.set\tat\n\t"
@@ -206,4 +209,24 @@ extern inline void * memmove(void * dest,const void * src, size_t n)
#define __USE_PORTABLE_memcmp
+static inline char * memscan(void * addr, unsigned char c, int size)
+{
+ if (!size)
+ return addr;
+ __asm__(".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+ "1:\tbeq\t$0,%1,2f\n\t"
+ "lbu\t$1,(%0)\n\t"
+ "subu\t%1,%1,1\n\t"
+ "bne\t$0,%1,1b\n\t"
+ "addiu\t%0,%0,1\n\t"
+ ".set\tat\n\t"
+ ".set\treorder\n"
+ "2:"
+ : "=d" (addr), "=d" (size)
+ : "0" (addr), "1" (size), "d" (c)
+ : "$1");
+
+ return addr;
+}
#endif /* _ASM_MIPS_STRING_H_ */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 5e0dbfe3c..3a3029b31 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -11,8 +11,9 @@
#ifndef _ASM_MIPS_SYSTEM_H_
#define _ASM_MIPS_SYSTEM_H_
+#include <linux/types.h>
#include <asm/segment.h>
-#include <mips/mipsregs.h>
+#include <asm/mipsregs.h>
/*
* move_to_user_mode() doesn't switch to user mode on the mips, since
@@ -25,46 +26,64 @@
#define move_to_user_mode()
#define sti() \
-__asm__ __volatile__( \
+__asm__ __volatile__( \
+ ".set\tnoat\n\t" \
"mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
- "ori\t$1,$1,1\n\t" \
+ "ori\t$1,$1,0x1f\n\t" \
+ "xori\t$1,$1,0x1e\n\t" \
"mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
- : /* no outputs */ \
- : /* no inputs */ \
- : "$1","memory")
+ ".set\tat" \
+ : /* no outputs */ \
+ : /* no inputs */ \
+ : "$1")
#define cli() \
-__asm__ __volatile__( \
+__asm__ __volatile__( \
+ ".set\tnoat\n\t" \
"mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
- "srl\t$1,$1,1\n\t" \
- "sll\t$1,$1,1\n\t" \
+ "ori\t$1,$1,1\n\t" \
+ "xori\t$1,$1,1\n\t" \
"mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
- : /* no outputs */ \
- : /* no inputs */ \
- : "$1","memory")
+ ".set\tat" \
+ : /* no outputs */ \
+ : /* no inputs */ \
+ : "$1")
#define nop() __asm__ __volatile__ ("nop")
-#define save_flags(x) \
-__asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- ".set\tnoat\n\t" \
- "mfc0\t%0,$12\n\t" \
- ".set\tat\n\t" \
- ".set\treorder" \
- : "=r" (x) \
- : /* no inputs */ \
- : "memory")
+extern ulong IRQ_vectors[256];
+extern ulong exception_handlers[256];
-#define restore_flags(x) \
-__asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- ".set\tnoat\n\t" \
- "mtc0\t%0,$12\n\t" \
- ".set\tat\n\t" \
- ".set\treorder" \
- : /* no output */ \
- : "r" (x) \
- : "memory")
+#define set_intr_gate(n,addr) \
+ IRQ_vectors[n] = (ulong) (addr)
+
+#define set_except_vector(n,addr) \
+ exception_handlers[n] = (ulong) (addr)
+
+/*
+ * atomic exchange of one word
+ *
+ * Fixme: This works only on MIPS ISA >=3
+ */
+#define atomic_exchange(m,r) \
+ __asm__ __volatile__( \
+ "1:\tll\t$8,(%2)\n\t" \
+ "move\t$9,%0\n\t" \
+ "sc\t$9,(%2)\n\t" \
+ "beq\t$0,$9,1b\n\t" \
+ : "=r" (r) \
+ : "0" (r), "r" (&(m)) \
+ : "$8","$9","memory");
+
+#define save_flags(x) \
+__asm__ __volatile__( \
+ "mfc0\t%0,$12\n\t" \
+ : "=r" (x)) \
+
+#define restore_flags(x) \
+__asm__ __volatile__( \
+ "mtc0\t%0,$12\n\t" \
+ : /* no output */ \
+ : "r" (x)); \
#endif /* _ASM_MIPS_SYSTEM_H_ */
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
new file mode 100644
index 000000000..236996dd5
--- /dev/null
+++ b/include/asm-mips/types.h
@@ -0,0 +1,39 @@
+#ifndef _ASM_MIPS_TYPES_H
+#define _ASM_MIPS_TYPES_H
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed long s32;
+typedef unsigned long u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#endif /* __KERNEL__ */
+
+/*
+ * These definitions double the definitions from <gnu/types.h>.
+ */
+#undef __FDELT
+#define __FDELT(d) ((d) / __NFDBITS)
+#undef __FDMASK
+#define __FDMASK(d) (1 << ((d) % __NFDBITS))
+#undef __FD_SET
+#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#undef __FD_CLR
+#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#undef __FD_ISSET
+#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif /* _ASM_MIPS_TYPES_H */
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 46ce46ff0..0776f3fdb 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -5,7 +5,7 @@
#define _syscall0(type,name) \
type name(void) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile (".set\tnoat\n\t" \
"li\t$1,%1\n\t" \
".set\tat\n\t" \
@@ -22,7 +22,7 @@ return -1; \
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile ("move\t$2,%2\n\t" \
".set\tnoat\n\t" \
"li\t$1,%1\n\t" \
@@ -40,7 +40,7 @@ return -1; \
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile ("move\t$2,%2\n\t" \
"move\t$3,%3\n\t" \
".set\tnoat\n\t" \
@@ -60,7 +60,7 @@ return -1; \
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name (atype a, btype b, ctype c) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile ("move\t$2,%2\n\t" \
"move\t$3,%3\n\t" \
"move\t$4,%4\n\t" \
@@ -82,7 +82,7 @@ return -1; \
#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
type name (atype a, btype b, ctype c, dtype d) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile (".set\tnoat\n\t" \
"move\t$2,%2\n\t" \
"move\t$3,%3\n\t" \
@@ -107,7 +107,7 @@ return -1; \
#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
type name (atype a,btype b,ctype c,dtype d,etype e) \
{ \
-register long __res; \
+register long __res __asm__ ("$2"); \
__asm__ volatile (".set\tnoat\n\t" \
"move\t$2,%2\n\t" \
"move\t$3,%3\n\t" \