diff options
Diffstat (limited to 'include/asm-mips')
-rw-r--r-- | include/asm-mips/bitops.h | 165 | ||||
-rw-r--r-- | include/asm-mips/bootinfo.h | 63 | ||||
-rw-r--r-- | include/asm-mips/cachectl.h | 32 | ||||
-rw-r--r-- | include/asm-mips/delay.h | 25 | ||||
-rw-r--r-- | include/asm-mips/dma.h | 271 | ||||
-rw-r--r-- | include/asm-mips/head.h | 9 | ||||
-rw-r--r-- | include/asm-mips/in.h | 34 | ||||
-rw-r--r-- | include/asm-mips/interrupt.h | 40 | ||||
-rw-r--r-- | include/asm-mips/io.h | 240 | ||||
-rw-r--r-- | include/asm-mips/irq.h | 18 | ||||
-rw-r--r-- | include/asm-mips/mipsconfig.h | 29 | ||||
-rw-r--r-- | include/asm-mips/mipsregs.h | 111 | ||||
-rw-r--r-- | include/asm-mips/mm.h | 94 | ||||
-rw-r--r-- | include/asm-mips/page.h | 90 | ||||
-rw-r--r-- | include/asm-mips/ptrace.h | 110 | ||||
-rw-r--r-- | include/asm-mips/regdef.h | 50 | ||||
-rw-r--r-- | include/asm-mips/sched.h | 240 | ||||
-rw-r--r-- | include/asm-mips/segment.h | 28 | ||||
-rw-r--r-- | include/asm-mips/signal.h | 28 | ||||
-rw-r--r-- | include/asm-mips/slots.h | 17 | ||||
-rw-r--r-- | include/asm-mips/stackframe.h | 176 | ||||
-rw-r--r-- | include/asm-mips/string.h | 25 | ||||
-rw-r--r-- | include/asm-mips/system.h | 83 | ||||
-rw-r--r-- | include/asm-mips/types.h | 39 | ||||
-rw-r--r-- | include/asm-mips/unistd.h | 12 |
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" \ |