diff options
Diffstat (limited to 'include/asm-sparc')
101 files changed, 9762 insertions, 2129 deletions
diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h new file mode 100644 index 000000000..6443e7612 --- /dev/null +++ b/include/asm-sparc/a.out.h @@ -0,0 +1,96 @@ +/* $Id: a.out.h,v 1.9 1996/05/29 13:44:54 ecd Exp $ */ +#ifndef __SPARC_A_OUT_H__ +#define __SPARC_A_OUT_H__ + +#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */ +#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */ + +struct exec { + unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */ + unsigned char a_toolversion:7; + unsigned char a_machtype; + unsigned short a_info; + unsigned long a_text; /* length of text, in bytes */ + unsigned long a_data; /* length of data, in bytes */ + unsigned long a_bss; /* length of bss, in bytes */ + unsigned long a_syms; /* length of symbol table, in bytes */ + unsigned long a_entry; /* where program begins */ + unsigned long a_trsize; + unsigned long a_drsize; +}; + +/* Where in the file does the text information begin? */ +#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec)) + +/* Where do the Symbols start? */ +#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \ + (x).a_data + (x).a_trsize + \ + (x).a_drsize) + +/* Where does text segment go in memory after being loaded? */ +#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \ + ((x).a_entry < SPARC_PGSIZE)) ? \ + 0 : SPARC_PGSIZE) + +/* And same for the data segment.. */ +#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \ + (N_TXTADDR(x) + (x).a_text) \ + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +/* + * Sparc relocation types + */ +enum reloc_type +{ + RELOC_8, + RELOC_16, + RELOC_32, /* simplest relocs */ + RELOC_DISP8, + RELOC_DISP16, + RELOC_DISP32, /* Disp's (pc-rel) */ + RELOC_WDISP30, + RELOC_WDISP22, /* SR word disp's */ + RELOC_HI22, + RELOC_22, /* SR 22-bit relocs */ + RELOC_13, + RELOC_LO10, /* SR 13&10-bit relocs */ + RELOC_SFA_BASE, + RELOC_SFA_OFF13, /* SR S.F.A. relocs */ + RELOC_BASE10, + RELOC_BASE13, + RELOC_BASE22, /* base_relative pic */ + RELOC_PC10, + RELOC_PC22, /* special pc-rel pic */ + RELOC_JMP_TBL, /* jmp_tbl_rel in pic */ + RELOC_SEGOFF16, /* ShLib offset-in-seg */ + RELOC_GLOB_DAT, + RELOC_JMP_SLOT, + RELOC_RELATIVE /* rtld relocs */ +}; + +/* + * Format of a relocation datum. + */ +struct relocation_info /* used when header.a_machtype == M_SPARC */ +{ + unsigned long r_address; /* relocation addr */ + unsigned int r_index:24; /* segment index or symbol index */ + unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */ + int r_pad:2; /* <unused> */ + enum reloc_type r_type:5; /* type of relocation to perform */ + long r_addend; /* addend for relocation value */ +}; + +#define N_RELOCATION_INFO_DECLARED 1 + +#ifdef __KERNEL__ + +#define STACK_TOP TASK_SIZE + +#endif + +#endif /* __SPARC_A_OUT_H__ */ diff --git a/include/asm-sparc/asi.h b/include/asm-sparc/asi.h index 4a404573d..f81ab33b9 100644 --- a/include/asm-sparc/asi.h +++ b/include/asm-sparc/asi.h @@ -1,43 +1,108 @@ +/* $Id: asi.h,v 1.16 1996/04/25 06:12:43 davem Exp $ */ #ifndef _SPARC_ASI_H #define _SPARC_ASI_H /* asi.h: Address Space Identifier values for the sparc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * Pioneer work for sun4m: Paul Hatchman (paul@sfe.com.au) + * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su> + */ + +/* The first batch are for the sun4c. */ + +#define ASI_NULL1 0x00 +#define ASI_NULL2 0x01 + +/* sun4c and sun4 control registers and mmu/vac ops */ +#define ASI_CONTROL 0x02 +#define ASI_SEGMAP 0x03 +#define ASI_PTE 0x04 +#define ASI_HWFLUSHSEG 0x05 +#define ASI_HWFLUSHPAGE 0x06 +#define ASI_REGMAP 0x06 +#define ASI_HWFLUSHCONTEXT 0x07 + +#define ASI_USERTXT 0x08 +#define ASI_KERNELTXT 0x09 +#define ASI_USERDATA 0x0a +#define ASI_KERNELDATA 0x0b + +/* VAC Cache flushing on sun4c and sun4 */ +#define ASI_FLUSHSEG 0x0c +#define ASI_FLUSHPG 0x0d +#define ASI_FLUSHCTX 0x0e - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ +/* SPARCstation-5: only 6 bits are decoded. */ +/* wo = Write Only, rw = Read Write; */ +/* ss = Single Size, as = All Sizes; */ +#define ASI_M_RES00 0x00 /* Don't touch... */ +#define ASI_M_UNA01 0x01 /* Same here... */ +#define ASI_M_MXCC 0x02 /* Access to TI VIKING MXCC registers */ +#define ASI_M_FLUSH_PROBE 0x03 /* Reference MMU Flush/Probe; rw, ss */ +#define ASI_M_MMUREGS 0x04 /* MMU Registers; rw, ss */ +#define ASI_M_TLBDIAG 0x05 /* MMU TLB only Diagnostics */ +#define ASI_M_DIAGS 0x06 /* Reference MMU Diagnostics */ +#define ASI_M_IODIAG 0x07 /* MMU I/O TLB only Diagnostics */ +#define ASI_M_USERTXT 0x08 /* Same as ASI_USERTXT; rw, as */ +#define ASI_M_KERNELTXT 0x09 /* Same as ASI_KERNELTXT; rw, as */ +#define ASI_M_USERDATA 0x0A /* Same as ASI_USERDATA; rw, as */ +#define ASI_M_KERNELDATA 0x0B /* Same as ASI_KERNELDATA; rw, as */ +#define ASI_M_TXTC_TAG 0x0C /* Instruction Cache Tag; rw, ss */ +#define ASI_M_TXTC_DATA 0x0D /* Instruction Cache Data; rw, ss */ +#define ASI_M_DATAC_TAG 0x0E /* Data Cache Tag; rw, ss */ +#define ASI_M_DATAC_DATA 0x0F /* Data Cache Data; rw, ss */ -/* These are sun4c, beware on other architectures. Although things should - * be similar under regular sun4's. +/* The following cache flushing ASIs work only with the 'sta' + * instruction. Results are unpredictable for 'swap' and 'ldstuba', + * so don't do it. */ -#include <linux/config.h> -#ifdef CONFIG_SUN4M -#include "asi4m.h" -#else +/* These ASI flushes affect external caches too. */ +#define ASI_M_FLUSH_PAGE 0x10 /* Flush I&D Cache Line (page); wo, ss */ +#define ASI_M_FLUSH_SEG 0x11 /* Flush I&D Cache Line (seg); wo, ss */ +#define ASI_M_FLUSH_REGION 0x12 /* Flush I&D Cache Line (region); wo, ss */ +#define ASI_M_FLUSH_CTX 0x13 /* Flush I&D Cache Line (context); wo, ss */ +#define ASI_M_FLUSH_USER 0x14 /* Flush I&D Cache Line (user); wo, ss */ -#define ASI_NULL1 0x0 -#define ASI_NULL2 0x1 +/* Block-copy operations are available only on certain V8 cpus. */ +#define ASI_M_BCOPY 0x17 /* Block copy */ -/* sun4c and sun4 control registers and mmu/vac ops */ -#define ASI_CONTROL 0x2 -#define ASI_SEGMAP 0x3 -#define ASI_PTE 0x4 -#define ASI_HWFLUSHSEG 0x5 /* These are to initiate hw flushes of the cache */ -#define ASI_HWFLUSHPAGE 0x6 -#define ASI_HWFLUSHCONTEXT 0x7 +/* These affect only the ICACHE and are Ross HyperSparc specific. */ +#define ASI_M_IFLUSH_PAGE 0x18 /* Flush I Cache Line (page); wo, ss */ +#define ASI_M_IFLUSH_SEG 0x19 /* Flush I Cache Line (seg); wo, ss */ +#define ASI_M_IFLUSH_REGION 0x1A /* Flush I Cache Line (region); wo, ss */ +#define ASI_M_IFLUSH_CTX 0x1B /* Flush I Cache Line (context); wo, ss */ +#define ASI_M_IFLUSH_USER 0x1C /* Flush I Cache Line (user); wo, ss */ +/* Block-fill operations are available on certain V8 cpus */ +#define ASI_M_BFILL 0x1F -#define ASI_USERTXT 0x8 -#define ASI_KERNELTXT 0x9 -#define ASI_USERDATA 0xa -#define ASI_KERNELDATA 0xb +/* This allows direct access to main memory, actually 0x20 to 0x2f are + * the available ASI's for physical ram pass-through, but I don't have + * any idea what the other ones do.... + */ -/* VAC Cache flushing on sun4c and sun4 */ +#define ASI_M_BYPASS 0x20 /* Reference MMU bypass; rw, as */ +#define ASI_M_FBMEM 0x29 /* Graphics card frame buffer access */ +#define ASI_M_VMEUS 0x2A /* VME user 16-bit access */ +#define ASI_M_VMEPS 0x2B /* VME priv 16-bit access */ +#define ASI_M_VMEUT 0x2C /* VME user 32-bit access */ +#define ASI_M_VMEPT 0x2D /* VME priv 32-bit access */ +#define ASI_M_SBUS 0x2E /* Direct SBus access */ +#define ASI_M_CTL 0x2F /* Control Space (ECC and MXCC are here) */ + + +/* This is ROSS HyperSparc only. */ +#define ASI_M_FLUSH_IWHOLE 0x31 /* Flush entire ICACHE; wo, ss */ + +/* Tsunami/Viking i/d cache flash clear. */ +#define ASI_M_IC_FLCLEAR 0x36 +#define ASI_M_DC_FLCLEAR 0x37 -#define ASI_FLUSHSEG 0xc /* These are for "software" flushes of the cache */ -#define ASI_FLUSHPG 0xd -#define ASI_FLUSHCTX 0xe +#define ASI_M_DCDR 0x39 /* Data Cache Diagnostics Register rw, ss */ +#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */ -#endif /* CONFIG_SUN4M */ #endif /* _SPARC_ASI_H */ diff --git a/include/asm-sparc/asi4m.h b/include/asm-sparc/asi4m.h deleted file mode 100644 index 68b1d21e7..000000000 --- a/include/asm-sparc/asi4m.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _SPARC_ASI4M_H -#define _SPARC_ASI4M_H - -/* asi4m.h: Address Space Identifier values for sun4m - - Copyright (C) 1995 Paul Hatchman (paul@sfe.com.au) -*/ - -#define ASI_PTE 0x0 - -#define ASI_NULL1 0x0 -#define ASI_NULL2 0x1 -#define ASI_CONTROL 0x4 /* hmm? */ -#define ASI_USERTXT 0x8 /* user text */ -#define ASI_KERNELTXT 0x9 /* kernel text */ -#define ASI_USERDATA 0xA /* user data */ -#define ASI_KERNELDATA 0xB /* kernel data */ - -/* cache flushing */ -#define ASI_FLUSHPG 0x10 -#define ASI_FLUSHSEG 0x11 -#define ASI_FLUSHRGN 0x12 -#define ASI_FLUSHCTX 0x13 - -/* MMU REGS */ -#define SRMMU_CTL 0x000 -#define SRMMU_CTP 0x100 /* set/get context pointer */ -#define SRMMU_CTX 0x200 /* get/set context */ -#endif _SPARC_ASI4M_H diff --git a/include/asm-sparc/asmmacro.h b/include/asm-sparc/asmmacro.h new file mode 100644 index 000000000..8bf441c27 --- /dev/null +++ b/include/asm-sparc/asmmacro.h @@ -0,0 +1,196 @@ +/* asmmacro.h: Assembler macros. + * + * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) + */ + +#ifndef _SPARC_ASMMACRO_H +#define _SPARC_ASMMACRO_H + +/* #define SMP_DEBUG */ + +#define GET_PROCESSOR_ID(reg) \ + rd %tbr, %reg; \ + srl %reg, 12, %reg; \ + and %reg, 3, %reg; + +#define GET_PROCESSOR_MID(reg, tmp) \ + GET_PROCESSOR_ID(reg) \ + set C_LABEL(mid_xlate), %tmp; \ + ldub [%tmp + %reg], %reg; + +#define GET_PROCESSOR_OFFSET(reg) \ + rd %tbr, %reg; \ + srl %reg, 10, %reg; \ + and %reg, 0xc, %reg; + +#define PROCESSOR_OFFSET_TO_ID(reg) \ + srl %reg, 2, %reg; + +#define PROCESSOR_ID_TO_OFFSET(reg) \ + sll %reg, 2, %reg; + +/* All trap entry points _must_ begin with this macro or else you + * lose. It makes sure the kernel has a proper window so that + * c-code can be called. + */ +#ifndef SMP_DEBUG +#define SAVE_ALL \ + sethi %hi(trap_setup), %l4; \ + jmpl %l4 + %lo(trap_setup), %l6; \ + nop; +#else +#define SAVE_ALL \ + GET_PROCESSOR_ID(l4); \ + set C_LABEL(trap_log), %l5; \ + sll %l4, 11, %l6; \ + add %l5, %l6, %l5; \ + set C_LABEL(trap_log_ent), %l6; \ + sll %l4, 2, %l4; \ + add %l6, %l4, %l6; \ + ld [%l6], %l6; \ + sll %l6, 3, %l6; \ + st %l1, [%l5 + %l6]; \ + add %l5, 4, %l5; \ + st %l0, [%l5 + %l6]; \ + set C_LABEL(trap_log_ent), %l5; \ + add %l5, %l4, %l5; \ + srl %l6, 3, %l6; \ + add %l6, 1, %l6; \ + and %l6, 255, %l6; \ + st %l6, [%l5]; \ + sethi %hi(trap_setup), %l4; \ + jmpl %l4 + %lo(trap_setup), %l6; \ + nop; +#endif + +/* All traps low-level code here must end with this macro. + * For SMP configurations the ret_trap_entry routine will + * have to appropriate code to actually release the kernel + * entry lock. + */ +#define RESTORE_ALL b ret_trap_entry; clr %l6; + +#ifndef __SMP__ + +#define ENTER_SYSCALL +#define LEAVE_SYSCALL +#define ENTER_IRQ +#define LEAVE_IRQ + +#else + +#define INCREMENT_COUNTER(symbol, tmp1, tmp2) \ + set C_LABEL(symbol), %tmp1; \ + ld [%tmp1], %tmp2; \ + add %tmp2, 1, %tmp2; \ + st %tmp2, [%tmp1]; + +#define DECREMENT_COUNTER(symbol, tmp1, tmp2) \ + set C_LABEL(symbol), %tmp1; \ + ld [%tmp1], %tmp2; \ + sub %tmp2, 1, %tmp2; \ + st %tmp2, [%tmp1]; + + /* This is so complicated I suggest you don't look at it. */ +#define ENTER_MASK(mask) \ + GET_PROCESSOR_OFFSET(l4) \ + set C_LABEL(smp_proc_in_lock), %l5; \ + ld [%l5 + %l4], %l6; \ + or %l6, mask, %l6; \ + st %l6, [%l5 + %l4]; \ +1: \ + set C_LABEL(kernel_flag), %l5; \ + ldstub [%l5], %l6; \ + cmp %l6, 0; \ + be 3f; \ + nop; \ + set C_LABEL(active_kernel_processor), %l5; \ + GET_PROCESSOR_ID(l4) \ + ldub [%l5], %l6; \ + cmp %l6, %l4; \ + be 4f; \ + nop; \ +2: \ + GET_PROCESSOR_MID(l4, l5) \ + set C_LABEL(sun4m_interrupts), %l5; \ + ld [%l5], %l5; \ + sll %l4, 12, %l4; \ + add %l5, %l4, %l5; \ + ld [%l5], %l4; \ + sethi %hi(0x80000000), %l6; \ + andcc %l6, %l4, %g0; \ + be 5f; \ + nop; \ + st %l6, [%l5 + 4]; \ + nop; nop; nop; \ + ld [%l5], %g0; \ + nop; nop; nop; \ + or %l0, PSR_PIL, %l4; \ + wr %l4, 0x0, %psr; \ + nop; nop; nop; \ + wr %l4, PSR_ET, %psr; \ + nop; nop; nop; \ + call C_LABEL(smp_message_irq); \ + nop; \ + wr %l0, 0x0, %psr; \ + nop; nop; nop; \ +5: \ + set C_LABEL(kernel_flag), %l5; \ + ldub [%l5], %l6; \ + cmp %l6, 0; \ + bne 2b; \ + nop; \ + b 1b; \ + nop; \ +3: \ + GET_PROCESSOR_ID(l4) \ + set C_LABEL(active_kernel_processor), %l5; \ + stb %l4, [%l5]; \ + GET_PROCESSOR_MID(l4, l5) \ + set C_LABEL(irq_rcvreg), %l5; \ + ld [%l5], %l5; \ + st %l4, [%l5]; \ +4: \ + +#define ENTER_SYSCALL \ + ENTER_MASK(SMP_FROM_SYSCALL) \ + INCREMENT_COUNTER(kernel_counter, l6, l5) \ + INCREMENT_COUNTER(syscall_count, l6, l5) + +#define ENTER_IRQ \ + ENTER_MASK(SMP_FROM_INT) \ + INCREMENT_COUNTER(kernel_counter, l6, l5) + +#define LEAVE_MASK(mask) \ + GET_PROCESSOR_OFFSET(l4) \ + set C_LABEL(smp_proc_in_lock), %l5; \ + ld [%l5 + %l4], %l6; \ + andn %l6, mask, %l6; \ + st %l6, [%l5 + %l4]; + +#define LEAVE_SYSCALL \ + LEAVE_MASK(SMP_FROM_SYSCALL) \ + DECREMENT_COUNTER(syscall_count, l6, l5) \ + set C_LABEL(kernel_counter), %l6; \ + ld [%l6], %l5; \ + subcc %l5, 1, %l5; \ + st %l5, [%l6]; \ + bne 1f; \ + nop; \ + set C_LABEL(active_kernel_processor), %l6; \ + mov NO_PROC_ID, %l5; \ + stb %l5, [%l6]; \ + set C_LABEL(kernel_flag), %l6; \ + stb %g0, [%l6]; \ +1: + +#define LEAVE_IRQ \ + LEAVE_MASK(SMP_FROM_INT) \ + INCREMENT_COUNTER(syscall_count, l6, l5) + + +#define RESTORE_ALL_FASTIRQ b,a ret_irq_entry; + +#endif /* !(__SMP__) */ + +#endif /* !(_SPARC_ASMMACRO_H) */ diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h new file mode 100644 index 000000000..3e46c262e --- /dev/null +++ b/include/asm-sparc/atomic.h @@ -0,0 +1,115 @@ +/* atomic.h: These really suck for now. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __ARCH_SPARC_ATOMIC__ +#define __ARCH_SPARC_ATOMIC__ + +typedef int atomic_t; + +#ifdef __KERNEL__ +#include <asm/system.h> +#include <asm/psr.h> + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +#define __atomic_fool_gcc(x) ((struct { int a[100]; } *)x) + +static __inline__ void atomic_add(atomic_t i, atomic_t *v) +{ + __asm__ __volatile__(" + rd %%psr, %%g2 + andcc %%g2, %2, %%g0 + be,a 1f + wr %%g2, %2, %%psr +1: ld [%0], %%g3 + add %%g3, %1, %%g3 + andcc %%g2, %2, %%g0 + st %%g3, [%0] + be,a 1f + wr %%g2, 0x0, %%psr +1: nop; nop; + " + : : "r" (__atomic_fool_gcc(v)), "r" (i), "i" (PSR_PIL) + : "g2", "g3"); +} + +static __inline__ void atomic_sub(atomic_t i, atomic_t *v) +{ + __asm__ __volatile__(" + rd %%psr, %%g2 + andcc %%g2, %2, %%g0 + be,a 1f + wr %%g2, %2, %%psr +1: ld [%0], %%g3 + sub %%g3, %1, %%g3 + andcc %%g2, %2, %%g0 + st %%g3, [%0] + be,a 1f + wr %%g2, 0x0, %%psr +1: nop; nop; + " + : : "r" (__atomic_fool_gcc(v)), "r" (i), "i" (PSR_PIL) + : "g2", "g3"); +} + +static __inline__ int atomic_add_return(atomic_t i, atomic_t *v) +{ + __asm__ __volatile__(" + rd %%psr, %%g2 + andcc %%g2, %3, %%g0 + be,a 1f + wr %%g2, %3, %%psr +1: ld [%1], %%g3 + add %%g3, %2, %0 + andcc %%g2, %3, %%g0 + st %0, [%1] + be,a 1f + wr %%g2, 0x0, %%psr +1: nop; nop; + " + : "=&r" (i) + : "r" (__atomic_fool_gcc(v)), "0" (i), "i" (PSR_PIL) + : "g2", "g3"); + + return i; +} + +static __inline__ int atomic_sub_return(atomic_t i, atomic_t *v) +{ + __asm__ __volatile__(" + rd %%psr, %%g2 + andcc %%g2, %3, %%g0 + be,a 1f + wr %%g2, %3, %%psr +1: ld [%1], %%g3 + sub %%g3, %2, %0 + andcc %%g2, %3, %%g0 + st %0, [%1] + be,a 1f + wr %%g2, 0x0, %%psr +1: nop; nop; + " + : "=&r" (i) + : "r" (__atomic_fool_gcc(v)), "0" (i), "i" (PSR_PIL) + : "g2", "g3"); + + return i; +} + +#define atomic_dec_return(v) atomic_sub_return(1,(v)) +#define atomic_inc_return(v) atomic_add_return(1,(v)) + +#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +#define atomic_inc(v) atomic_add(1,(v)) +#define atomic_dec(v) atomic_sub(1,(v)) + +#endif /* !(__KERNEL__) */ + +#endif /* !(__ARCH_SPARC_ATOMIC__) */ diff --git a/include/asm-sparc/atops.h b/include/asm-sparc/atops.h new file mode 100644 index 000000000..0bb70752d --- /dev/null +++ b/include/asm-sparc/atops.h @@ -0,0 +1,22 @@ +/* atops.h: Atomic SPARC operations. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_ATOPS_H +#define _SPARC_ATOPS_H + +#ifdef __SMP__ + +extern __inline__ __volatile__ unsigned char ldstub(volatile unsigned char *lock) +{ + volatile unsigned char retval; + + __asm__ __volatile__("ldstub [%1], %0\n\t" : + "=&r" (retval) : + "r" (lock)); + return retval; +} + +#endif + +#endif diff --git a/include/asm-sparc/auxio.h b/include/asm-sparc/auxio.h new file mode 100644 index 000000000..be4107408 --- /dev/null +++ b/include/asm-sparc/auxio.h @@ -0,0 +1,70 @@ +/* $Id: auxio.h,v 1.14 1996/10/31 06:29:10 davem Exp $ + * auxio.h: Definitions and code for the Auxiliary I/O register. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_AUXIO_H +#define _SPARC_AUXIO_H + +#include <asm/system.h> +#include <asm/vaddrs.h> + +extern unsigned char *auxio_register; + +/* This register is an unsigned char in IO space. It does two things. + * First, it is used to control the front panel LED light on machines + * that have it (good for testing entry points to trap handlers and irq's) + * Secondly, it controls various floppy drive parameters. + */ +#define AUXIO_ORMEIN 0xf0 /* All writes must set these bits. */ +#define AUXIO_ORMEIN4M 0xc0 /* sun4m - All writes must set these bits. */ +#define AUXIO_FLPY_DENS 0x20 /* Floppy density, high if set. Read only. */ +#define AUXIO_FLPY_DCHG 0x10 /* A disk change occurred. Read only. */ +#define AUXIO_EDGE_ON 0x10 /* sun4m - On means Jumper block is in. */ +#define AUXIO_FLPY_DSEL 0x08 /* Drive select/start-motor. Write only. */ +#define AUXIO_LINK_TEST 0x08 /* sun4m - On means TPE Carrier detect. */ + +/* Set the following to one, then zero, after doing a pseudo DMA transfer. */ +#define AUXIO_FLPY_TCNT 0x04 /* Floppy terminal count. Write only. */ + +/* Set the following to zero to eject the floppy. */ +#define AUXIO_FLPY_EJCT 0x02 /* Eject floppy disk. Write only. */ +#define AUXIO_LED 0x01 /* On if set, off if unset. Read/Write */ + +#define AUXREG ((volatile unsigned char *)(auxio_register)) + +/* These are available on sun4c */ +#define TURN_ON_LED if (AUXREG) *AUXREG = (*AUXREG | AUXIO_ORMEIN | AUXIO_LED) +#define TURN_OFF_LED if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_LED)) +#define FLIP_LED if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) ^ AUXIO_LED) +#define FLPY_MOTORON if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_DSEL) +#define FLPY_MOTOROFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL)) +#define FLPY_TCNTON if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_TCNT) +#define FLPY_TCNTOFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT)) + +#ifndef __ASSEMBLY__ +extern __inline__ void set_auxio(unsigned char bits_on, unsigned char bits_off) +{ + unsigned char regval; + unsigned long flags; + + save_flags(flags); cli(); + + switch(sparc_cpu_model) { + case sun4c: + regval = *AUXREG; + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; + break; + case sun4m: + regval = *AUXREG; + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; + break; + default: + panic("Can't set AUXIO register on this machine."); + }; + + restore_flags(flags); +} +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_SPARC_AUXIO_H) */ diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h index 241e5e8c1..85d86c6dd 100644 --- a/include/asm-sparc/bitops.h +++ b/include/asm-sparc/bitops.h @@ -1,121 +1,202 @@ +/* $Id: bitops.h,v 1.36 1996/09/29 22:57:21 davem Exp $ + * bitops.h: Bit string operations on the Sparc. + * + * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright 1996 Eddie C. Dost (ecd@skynet.be) + */ + #ifndef _SPARC_BITOPS_H #define _SPARC_BITOPS_H -/* - * Copyright 1994, David S. Miller (davem@caip.rutgers.edu). - */ +#include <linux/kernel.h> +#ifndef __KERNEL__ -/* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0' - * is in the highest of the four bytes and bit '31' is the high bit - * within the first byte. Sparc is BIG-Endian. Unless noted otherwise - * all bit-ops return 0 if bit was previously clear and != 0 otherwise. +/* User mode bitops, defined here for convenience. Note: these are not + * atomic, so packages like nthreads should do some locking around these + * themself. */ -/* For now, the sun4c implementation will disable and enable traps - * in order to insure atomicity. Things will have to be different - * for sun4m (ie. SMP) no doubt. - */ +#define __SMPVOL -extern __inline__ unsigned int set_bit(unsigned int nr, void *addr) +extern __inline__ unsigned long set_bit(unsigned long nr, void *addr) { - register unsigned long retval, tmp, mask, psr; - - __asm__ __volatile__("or %%g0, 0x1, %3\n\t" /* produce the mask */ - "sll %3, %4, %3\n\t" - "rd %%psr, %5\n\t" /* read the psr */ - "wr %5, 0x20, %%psr\n\t" /* traps disabled */ - "ld [%1], %2\n\t" /* critical section */ - "and %3, %2, %0\n\t" - "or %3, %2, %2\n\t" - "st %2, [%1]\n\t" - "wr %5, 0x0, %%psr\n\t" : /* re-enable traps */ - "=r" (retval) : - "r" (addr), "r" (tmp=0), "r" (mask=0), - "r" (nr), "r" (psr=0)); - - return retval; /* confuse gcc :-) */ - + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + ld [%0], %%g3 + or %%g3, %2, %%g2 + st %%g2, [%0] + and %%g3, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask) + : "g2", "g3"); + + return (unsigned long) ADDR; } -extern __inline__ unsigned int clear_bit(unsigned int nr, void *addr) +extern __inline__ unsigned long clear_bit(unsigned long nr, void *addr) { - register unsigned long retval, tmp, mask, psr; - - __asm__ __volatile__("or %%g0, 0x1, %3\n\t" - "sll %3, %4, %3\n\t" - "rd %%psr, %5\n\t" - "wr %5, 0x20, %%psr\n\t" /* disable traps */ - "ld [%1], %2\n\t" - "and %2, %3, %0\n\t" /* get old bit */ - "andn %2, %3, %2\n\t" /* set new val */ - "st %2, [%1]\n\t" - "wr %5, 0x0, %%psr\n\t" : /* enable traps */ - "=r" (retval) : - "r" (addr), "r" (tmp=0), "r" (mask=0), - "r" (nr), "r" (psr=0)); - - return retval; /* confuse gcc ;-) */ - + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + ld [%0], %%g3 + andn %%g3, %2, %%g2 + st %%g2, [%0] + and %%g3, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask) + : "g2", "g3"); + + return (unsigned long) ADDR; } -extern __inline__ unsigned int change_bit(unsigned int nr, void *addr) +extern __inline__ unsigned long change_bit(unsigned long nr, void *addr) { - register unsigned long retval, tmp, mask, psr; + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + ld [%0], %%g3 + xor %%g3, %2, %%g2 + st %%g2, [%0] + and %%g3, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask) + : "g2", "g3"); + + return (unsigned long) ADDR; +} - __asm__ __volatile__("or %%g0, 0x1, %3\n\t" - "sll %3, %4, %3\n\t" - "rd %%psr, %5\n\t" - "wr %5, 0x20, %%psr\n\t" /* disable traps */ - "ld [%1], %2\n\t" - "and %3, %2, %0\n\t" /* get old bit val */ - "xor %3, %2, %2\n\t" /* set new val */ - "st %2, [%1]\n\t" - "wr %5, 0x0, %%psr\n\t" : /* enable traps */ - "=r" (retval) : - "r" (addr), "r" (tmp=0), "r" (mask=0), - "r" (nr), "r" (psr=0)); +#else /* __KERNEL__ */ - return retval; /* confuse gcc ;-) */ +#include <asm/system.h> -} +#ifdef __SMP__ +#define __SMPVOL volatile +#else +#define __SMPVOL +#endif -/* The following routine need not be atomic. */ +/* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0' + * is in the highest of the four bytes and bit '31' is the high bit + * within the first byte. Sparc is BIG-Endian. Unless noted otherwise + * all bit-ops return 0 if bit was previously clear and != 0 otherwise. + */ -extern __inline__ unsigned int test_bit(int nr, void *addr) +extern __inline__ unsigned long set_bit(unsigned long nr, __SMPVOL void *addr) { - register unsigned long retval, tmp; - - __asm__ __volatile__("ld [%1], %2\n\t" - "or %%g0, 0x1, %0\n\t" - "sll %0, %3, %0\n\t" - "and %0, %2, %0\n\t" : - "=r" (retval) : - "r" (addr), "r" (tmp=0), - "r" (nr)); + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ld [%0], %%g4 + or %%g4, %2, %%g2 + andcc %%g3, %3, %%g0 + st %%g2, [%0] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + and %%g4, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask), "i" (PSR_PIL) + : "g2", "g3", "g4"); + + return (unsigned long) ADDR; +} - return retval; /* confuse gcc :> */ +extern __inline__ unsigned long clear_bit(unsigned long nr, __SMPVOL void *addr) +{ + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ld [%0], %%g4 + andn %%g4, %2, %%g2 + andcc %%g3, %3, %%g0 + st %%g2, [%0] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + and %%g4, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask), "i" (PSR_PIL) + : "g2", "g3", "g4"); + + return (unsigned long) ADDR; +} +extern __inline__ unsigned long change_bit(unsigned long nr, __SMPVOL void *addr) +{ + int mask; + unsigned long *ADDR = (unsigned long *) addr; + + ADDR += nr >> 5; + mask = 1 << (nr & 31); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ld [%0], %%g4 + xor %%g4, %2, %%g2 + andcc %%g3, %3, %%g0 + st %%g2, [%0] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + and %%g4, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask), "i" (PSR_PIL) + : "g2", "g3", "g4"); + + return (unsigned long) ADDR; } -/* There has to be a faster way to do this, sigh... */ +#endif /* __KERNEL__ */ -extern __inline__ unsigned long ffz(unsigned long word) +/* The following routine need not be atomic. */ +extern __inline__ unsigned long test_bit(int nr, __const__ __SMPVOL void *addr) { - register unsigned long cnt, tmp, tmp2; - - cnt = 0; + return 1UL & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31)); +} - __asm__("or %%g0, %3, %2\n\t" - "1: and %2, 0x1, %1\n\t" - "srl %2, 0x1, %2\n\t" - "cmp %1, 0\n\t" - "bne,a 1b\n\t" - "add %0, 0x1, %0\n\t" : - "=r" (cnt) : - "r" (tmp=0), "r" (tmp2=0), "r" (word)); +/* The easy/cheese version for now. */ +extern __inline__ unsigned long ffz(unsigned long word) +{ + unsigned long result = 0; - return cnt; + while(word & 1) { + result++; + word >>= 1; + } + return result; } /* find_next_zero_bit() finds the first zero bit in a bit string of length @@ -125,40 +206,38 @@ extern __inline__ unsigned long ffz(unsigned long word) extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) { - unsigned long *p = ((unsigned long *) addr) + (offset >> 6); - unsigned long result = offset & ~31UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) - { - tmp = *(p++); - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (~tmp) - goto found_middle; - size -= 32; - result += 32; - } - while (size & ~32UL) - { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) + goto found_first; + if (~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while (size & ~31UL) { + if (~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = *p; found_first: - tmp |= ~0UL << size; + tmp |= ~0UL << size; found_middle: - return result + ffz(tmp); + return result + ffz(tmp); } /* Linus sez that gcc can optimize the following correctly, we'll see if this @@ -168,6 +247,169 @@ found_middle: #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) +#ifndef __KERNEL__ + +extern __inline__ int __ext2_set_bit(int nr, void *addr) +{ + int mask; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + __asm__ __volatile__(" + ldub [%0], %%g3 + or %%g3, %2, %%g2 + stb %%g2, [%0] + and %%g3, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask) + : "g2", "g3"); + + return (int) ADDR; +} + +extern __inline__ int __ext2_clear_bit(int nr, void *addr) +{ + int mask; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + __asm__ __volatile__(" + ldub [%0], %%g3 + andn %%g3, %2, %%g2 + stb %%g2, [%0] + and %%g3, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask) + : "g2", "g3"); + + return (int) ADDR; +} + +#else /* __KERNEL__ */ + +/* Now for the ext2 filesystem bit operations and helper routines. */ + +extern __inline__ int __ext2_set_bit(int nr,void * addr) +{ + int mask; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ldub [%0], %%g4 + or %%g4, %2, %%g2 + andcc %%g3, %3, %%g0 + stb %%g2, [%0] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + and %%g4, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask), "i" (PSR_PIL) + : "g2", "g3", "g4"); + + return (int) ADDR; +} + +extern __inline__ int __ext2_clear_bit(int nr, void * addr) +{ + int mask; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ldub [%0], %%g4 + andn %%g4, %2, %%g2 + andcc %%g3, %3, %%g0 + stb %%g2, [%0] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + and %%g4, %2, %0 + " + : "=&r" (ADDR) + : "0" (ADDR), "r" (mask), "i" (PSR_PIL) + : "g2", "g3", "g4"); + + return (int) ADDR; +} + +#endif /* __KERNEL__ */ + +extern __inline__ int __ext2_test_bit(int nr, __const__ void * addr) +{ + int mask; + __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return ((mask & *ADDR) != 0); +} + +extern __inline__ unsigned short __swab16(unsigned short value) +{ + return ((value >> 8) | (value << 8)); +} + +extern __inline__ unsigned long __swab32(unsigned long value) +{ + return ((value >> 24) | ((value >> 8) & 0xff00) | + ((value << 8) & 0xff0000) | (value << 24)); +} + +#define __ext2_find_first_zero_bit(addr, size) \ + __ext2_find_next_zero_bit((addr), (size), 0) + +extern __inline__ unsigned long __ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if(offset) { + tmp = *(p++); + tmp |= __swab32(~0UL >> (32-offset)); + if(size < 32) + goto found_first; + if(~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while(size & ~31UL) { + if(~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if(!size) + return result; + tmp = *p; + +found_first: + return result + ffz(__swab32(tmp) | (~0UL << size)); +found_middle: + return result + ffz(__swab32(tmp)); +} #endif /* defined(_SPARC_BITOPS_H) */ diff --git a/include/asm-sparc/bsderrno.h b/include/asm-sparc/bsderrno.h new file mode 100644 index 000000000..54a75be43 --- /dev/null +++ b/include/asm-sparc/bsderrno.h @@ -0,0 +1,94 @@ +/* $Id: bsderrno.h,v 1.3 1996/04/25 06:12:47 davem Exp $ + * bsderrno.h: Error numbers for NetBSD binary compatibility + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_BSDERRNO_H +#define _SPARC_BSDERRNO_H + +#define BSD_EPERM 1 /* Operation not permitted */ +#define BSD_ENOENT 2 /* No such file or directory */ +#define BSD_ESRCH 3 /* No such process */ +#define BSD_EINTR 4 /* Interrupted system call */ +#define BSD_EIO 5 /* Input/output error */ +#define BSD_ENXIO 6 /* Device not configured */ +#define BSD_E2BIG 7 /* Argument list too long */ +#define BSD_ENOEXEC 8 /* Exec format error */ +#define BSD_EBADF 9 /* Bad file descriptor */ +#define BSD_ECHILD 10 /* No child processes */ +#define BSD_EDEADLK 11 /* Resource deadlock avoided */ +#define BSD_ENOMEM 12 /* Cannot allocate memory */ +#define BSD_EACCES 13 /* Permission denied */ +#define BSD_EFAULT 14 /* Bad address */ +#define BSD_ENOTBLK 15 /* Block device required */ +#define BSD_EBUSY 16 /* Device busy */ +#define BSD_EEXIST 17 /* File exists */ +#define BSD_EXDEV 18 /* Cross-device link */ +#define BSD_ENODEV 19 /* Operation not supported by device */ +#define BSD_ENOTDIR 20 /* Not a directory */ +#define BSD_EISDIR 21 /* Is a directory */ +#define BSD_EINVAL 22 /* Invalid argument */ +#define BSD_ENFILE 23 /* Too many open files in system */ +#define BSD_EMFILE 24 /* Too many open files */ +#define BSD_ENOTTY 25 /* Inappropriate ioctl for device */ +#define BSD_ETXTBSY 26 /* Text file busy */ +#define BSD_EFBIG 27 /* File too large */ +#define BSD_ENOSPC 28 /* No space left on device */ +#define BSD_ESPIPE 29 /* Illegal seek */ +#define BSD_EROFS 30 /* Read-only file system */ +#define BSD_EMLINK 31 /* Too many links */ +#define BSD_EPIPE 32 /* Broken pipe */ +#define BSD_EDOM 33 /* Numerical argument out of domain */ +#define BSD_ERANGE 34 /* Result too large */ +#define BSD_EAGAIN 35 /* Resource temporarily unavailable */ +#define BSD_EWOULDBLOCK EAGAIN /* Operation would block */ +#define BSD_EINPROGRESS 36 /* Operation now in progress */ +#define BSD_EALREADY 37 /* Operation already in progress */ +#define BSD_ENOTSOCK 38 /* Socket operation on non-socket */ +#define BSD_EDESTADDRREQ 39 /* Destination address required */ +#define BSD_EMSGSIZE 40 /* Message too long */ +#define BSD_EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define BSD_ENOPROTOOPT 42 /* Protocol not available */ +#define BSD_EPROTONOSUPPORT 43 /* Protocol not supported */ +#define BSD_ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define BSD_EOPNOTSUPP 45 /* Operation not supported */ +#define BSD_EPFNOSUPPORT 46 /* Protocol family not supported */ +#define BSD_EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define BSD_EADDRINUSE 48 /* Address already in use */ +#define BSD_EADDRNOTAVAIL 49 /* Can't assign requested address */ +#define BSD_ENETDOWN 50 /* Network is down */ +#define BSD_ENETUNREACH 51 /* Network is unreachable */ +#define BSD_ENETRESET 52 /* Network dropped connection on reset */ +#define BSD_ECONNABORTED 53 /* Software caused connection abort */ +#define BSD_ECONNRESET 54 /* Connection reset by peer */ +#define BSD_ENOBUFS 55 /* No buffer space available */ +#define BSD_EISCONN 56 /* Socket is already connected */ +#define BSD_ENOTCONN 57 /* Socket is not connected */ +#define BSD_ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define BSD_ETOOMANYREFS 59 /* Too many references: can't splice */ +#define BSD_ETIMEDOUT 60 /* Operation timed out */ +#define BSD_ECONNREFUSED 61 /* Connection refused */ +#define BSD_ELOOP 62 /* Too many levels of symbolic links */ +#define BSD_ENAMETOOLONG 63 /* File name too long */ +#define BSD_EHOSTDOWN 64 /* Host is down */ +#define BSD_EHOSTUNREACH 65 /* No route to host */ +#define BSD_ENOTEMPTY 66 /* Directory not empty */ +#define BSD_EPROCLIM 67 /* Too many processes */ +#define BSD_EUSERS 68 /* Too many users */ +#define BSD_EDQUOT 69 /* Disc quota exceeded */ +#define BSD_ESTALE 70 /* Stale NFS file handle */ +#define BSD_EREMOTE 71 /* Too many levels of remote in path */ +#define BSD_EBADRPC 72 /* RPC struct is bad */ +#define BSD_ERPCMISMATCH 73 /* RPC version wrong */ +#define BSD_EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define BSD_EPROGMISMATCH 75 /* Program version wrong */ +#define BSD_EPROCUNAVAIL 76 /* Bad procedure for program */ +#define BSD_ENOLCK 77 /* No locks available */ +#define BSD_ENOSYS 78 /* Function not implemented */ +#define BSD_EFTYPE 79 /* Inappropriate file type or format */ +#define BSD_EAUTH 80 /* Authentication error */ +#define BSD_ENEEDAUTH 81 /* Need authenticator */ +#define BSD_ELAST 81 /* Must be equal largest errno */ + +#endif /* !(_SPARC_BSDERRNO_H) */ diff --git a/include/asm-sparc/bugs.h b/include/asm-sparc/bugs.h index 55f5434ad..534ce05ff 100644 --- a/include/asm-sparc/bugs.h +++ b/include/asm-sparc/bugs.h @@ -1,48 +1,7 @@ -/* include/asm-sparc/bugs.h: Sparc probes for various bugs. +/* $Id: bugs.h,v 1.5 1995/11/25 02:31:18 davem Exp $ + * include/asm-sparc/bugs.h: Sparc probes for various bugs. * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) */ -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -#define CONFIG_BUGSPARC - -#include <asm/openprom.h> - -extern struct linux_romvec *romvec; -extern int tbase_needs_unmapping; /* We do the bug workaround in pagetables.c */ - -static void check_mmu(void) -{ - register struct linux_romvec *lvec; - register int root_node; - unsigned int present; - - lvec = romvec; - - root_node = (*(romvec->pv_nodeops->no_nextnode))(0); - tbase_needs_unmapping=0; - - present = 0; - (*(romvec->pv_nodeops->no_getprop))(root_node, "buserr-type", - (char *) &present); - if(present == 1) - { - tbase_needs_unmapping=1; - printk("MMU bug found: not allowing trapbase to be cached\n"); - } - - return; -} - - -static void -check_bugs(void) -{ - check_mmu(); -} +static void check_bugs(void) { } diff --git a/include/asm-sparc/byteorder.h b/include/asm-sparc/byteorder.h index b734cf8a6..4f1cd2e65 100644 --- a/include/asm-sparc/byteorder.h +++ b/include/asm-sparc/byteorder.h @@ -1,85 +1,24 @@ +/* $Id: byteorder.h,v 1.9 1996/08/30 05:21:34 davem Exp $ */ #ifndef _SPARC_BYTEORDER_H #define _SPARC_BYTEORDER_H -#undef ntohl -#undef ntohs -#undef htonl -#undef htons +#define ntohl(x) x +#define ntohs(x) x +#define htonl(x) x +#define htons(x) x -#define BIG_ENDIAN -#define BIG_ENDIAN_BITFIELD +/* Some programs depend upon these being around. */ +#define __constant_ntohl(x) x +#define __constant_ntohs(x) x +#define __constant_htonl(x) x +#define __constant_htons(x) x -extern unsigned long int ntohl(unsigned long int); -extern unsigned short int ntohs(unsigned short int); -extern unsigned long int htonl(unsigned long int); -extern unsigned short int htons(unsigned short int); - -extern unsigned long int __ntohl(unsigned long int); -extern unsigned short int __ntohs(unsigned short int); -extern unsigned long int __constant_ntohl(unsigned long int); -extern unsigned short int __constant_ntohs(unsigned short int); - -/* - * The constant and non-constant versions here are the same. - * Maybe I'll come up with an alpha-optimized routine for the - * non-constant ones (the constant ones don't need it: gcc - * will optimize it to the correct constant) - */ - -extern __inline__ unsigned long int -__ntohl(unsigned long int x) -{ - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); -} - -extern __inline__ unsigned long int -__constant_ntohl(unsigned long int x) -{ - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); -} - -extern __inline__ unsigned short int -__ntohs(unsigned short int x) -{ - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); -} - -extern __inline__ unsigned short int -__constant_ntohs(unsigned short int x) -{ - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); -} - -#define __htonl(x) __ntohl(x) -#define __htons(x) __ntohs(x) -#define __constant_htonl(x) __constant_ntohl(x) -#define __constant_htons(x) __constant_ntohs(x) +#ifndef __BIG_ENDIAN +#define __BIG_ENDIAN 4321 +#endif -#ifdef __OPTIMIZE__ -# define ntohl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_ntohl((x)) : \ - __ntohl((x))) -# define ntohs(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_ntohs((x)) : \ - __ntohs((x))) -# define htonl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_htonl((x)) : \ - __htonl((x))) -# define htons(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_htons((x)) : \ - __htons((x))) +#ifndef __BIG_ENDIAN_BITFIELD +#define __BIG_ENDIAN_BITFIELD #endif #endif /* !(_SPARC_BYTEORDER_H) */ diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h new file mode 100644 index 000000000..f537c5cc3 --- /dev/null +++ b/include/asm-sparc/cache.h @@ -0,0 +1,123 @@ +/* $Id: cache.h,v 1.5 1996/08/29 09:48:06 davem Exp $ + * cache.h: Cache specific code for the Sparc. These include flushing + * and direct tag/data line access. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_CACHE_H +#define _SPARC_CACHE_H + +#include <asm/asi.h> + +/* Direct access to the instruction cache is provided through and + * alternate address space. The IDC bit must be off in the ICCR on + * HyperSparcs for these accesses to work. The code below does not do + * any checking, the caller must do so. These routines are for + * diagnostics only, but could end up being useful. Use with care. + * Also, you are asking for trouble if you execute these in one of the + * three instructions following a %asr/%psr access or modification. + */ + +/* First, cache-tag access. */ +extern __inline__ unsigned int get_icache_tag(int setnum, int tagnum) +{ + unsigned int vaddr, retval; + + vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5); + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (vaddr), "i" (ASI_M_TXTC_TAG)); + return retval; +} + +extern __inline__ void put_icache_tag(int setnum, int tagnum, unsigned int entry) +{ + unsigned int vaddr; + + vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5); + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (entry), "r" (vaddr), "i" (ASI_M_TXTC_TAG) : + "memory"); +} + +/* Second cache-data access. The data is returned two-32bit quantities + * at a time. + */ +extern __inline__ void get_icache_data(int setnum, int tagnum, int subblock, + unsigned int *data) +{ + unsigned int value1, value2, vaddr; + + vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) | + ((subblock&0x3) << 3); + __asm__ __volatile__("ldda [%2] %3, %%g2\n\t" + "or %%g0, %%g2, %0\n\t" + "or %%g0, %%g3, %1\n\t" : + "=r" (value1), "=r" (value2) : + "r" (vaddr), "i" (ASI_M_TXTC_DATA) : + "g2", "g3"); + data[0] = value1; data[1] = value2; +} + +extern __inline__ void put_icache_data(int setnum, int tagnum, int subblock, + unsigned int *data) +{ + unsigned int value1, value2, vaddr; + + vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) | + ((subblock&0x3) << 3); + value1 = data[0]; value2 = data[1]; + __asm__ __volatile__("or %%g0, %0, %%g2\n\t" + "or %%g0, %1, %%g3\n\t" + "stda %%g2, [%2] %3\n\t" : : + "r" (value1), "r" (value2), + "r" (vaddr), "i" (ASI_M_TXTC_DATA) : + "g2", "g3", "memory" /* no joke */); +} + +/* Different types of flushes with the ICACHE. Some of the flushes + * affect both the ICACHE and the external cache. Others only clear + * the ICACHE entries on the cpu itself. V8's (most) allow + * granularity of flushes on the packet (element in line), whole line, + * and entire cache (ie. all lines) level. The ICACHE only flushes are + * ROSS HyperSparc specific and are in ross.h + */ + +/* Flushes which clear out both the on-chip and external caches */ +extern __inline__ void flush_ei_page(unsigned int addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_PAGE) : + "memory"); +} + +extern __inline__ void flush_ei_seg(unsigned int addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_SEG) : + "memory"); +} + +extern __inline__ void flush_ei_region(unsigned int addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_REGION) : + "memory"); +} + +extern __inline__ void flush_ei_ctx(unsigned int addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_CTX) : + "memory"); +} + +extern __inline__ void flush_ei_user(unsigned int addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_USER) : + "memory"); +} + +#endif /* !(_SPARC_CACHE_H) */ diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h new file mode 100644 index 000000000..a11777025 --- /dev/null +++ b/include/asm-sparc/checksum.h @@ -0,0 +1,163 @@ +/* $Id: checksum.h,v 1.22 1996/11/10 21:28:25 davem Exp $ */ +#ifndef __SPARC_CHECKSUM_H +#define __SPARC_CHECKSUM_H + +/* checksum.h: IP/UDP/TCP checksum routines on the Sparc. + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1995 Miguel de Icaza + * Copyright(C) 1996 David S. Miller + * Copyright(C) 1996 Eddie C. Dost + * + * derived from: + * Alpha checksum c-code + * ix86 inline assembly + * RFC1071 Computing the Internet Checksum + */ + +/* computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum); + +/* the same as csum_partial, but copies from fs:src while it + * checksums + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +extern unsigned int csum_partial_copy(char *src, char *dst, int len, int sum); + +#define csum_partial_copy_fromuser(s, d, l, w) \ + csum_partial_copy((char *) (s), (d), (l), (w)) + +/* ihl is always 5 or greater, almost always is 5, and iph is word aligned + * the majority of the time. + */ +extern __inline__ unsigned short ip_fast_csum(__const__ unsigned char *iph, + unsigned int ihl) +{ + unsigned short sum; + + /* Note: We must read %2 before we touch %0 for the first time, + * because GCC can legitimately use the same register for + * both operands. + */ + __asm__ __volatile__("sub\t%2, 4, %%g4\n\t" + "ld\t[%1 + 0x00], %0\n\t" + "ld\t[%1 + 0x04], %%g2\n\t" + "ld\t[%1 + 0x08], %%g3\n\t" + "addcc\t%%g2, %0, %0\n\t" + "addxcc\t%%g3, %0, %0\n\t" + "ld\t[%1 + 0x0c], %%g2\n\t" + "ld\t[%1 + 0x10], %%g3\n\t" + "addxcc\t%%g2, %0, %0\n\t" + "addx\t%0, %%g0, %0\n" + "1:\taddcc\t%%g3, %0, %0\n\t" + "add\t%1, 4, %1\n\t" + "addxcc\t%0, %%g0, %0\n\t" + "subcc\t%%g4, 1, %%g4\n\t" + "be,a\t2f\n\t" + "sll\t%0, 16, %%g2\n\t" + "b\t1b\n\t" + "ld\t[%1 + 0x10], %%g3\n" + "2:\taddcc\t%0, %%g2, %%g2\n\t" + "srl\t%%g2, 16, %0\n\t" + "addx\t%0, %%g0, %0\n\t" + "xnor\t%%g0, %0, %0" + : "=r" (sum), "=&r" (iph) + : "r" (ihl), "1" (iph) + : "g2", "g3", "g4"); + return sum; +} + +/* computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern __inline__ unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned int len, + unsigned short proto, + unsigned int sum) +{ + __asm__ __volatile__("addcc\t%1, %0, %0\n\t" + "addxcc\t%2, %0, %0\n\t" + "addxcc\t%3, %0, %0\n\t" + "addx\t%0, %%g0, %0\n\t" + "sll\t%0, 16, %1\n\t" + "addcc\t%1, %0, %0\n\t" + "srl\t%0, 16, %0\n\t" + "addx\t%0, %%g0, %0\n\t" + "xnor\t%%g0, %0, %0" + : "=r" (sum), "=r" (saddr) + : "r" (daddr), "r" ((proto<<16)+len), "0" (sum), + "1" (saddr)); + return sum; +} + +/* Fold a partial checksum without adding pseudo headers. */ +extern __inline__ unsigned int csum_fold(unsigned int sum) +{ + unsigned int tmp; + + __asm__ __volatile__("addcc\t%0, %1, %1\n\t" + "srl\t%1, 16, %1\n\t" + "addx\t%1, %%g0, %1\n\t" + "xnor\t%%g0, %1, %0" + : "=&r" (sum), "=r" (tmp) + : "0" (sum), "1" (sum<<16)); + return sum; +} + +#define _HAVE_ARCH_IPV6_CSUM + +static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, + struct in6_addr *daddr, + __u16 len, + unsigned short proto, + unsigned int sum) +{ + __asm__ __volatile__ (" + addcc %3, %4, %%g4 + addxcc %5, %%g4, %%g4 + ld [%2 + 0x0c], %%g2 + ld [%2 + 0x08], %%g3 + addxcc %%g2, %%g4, %%g4 + ld [%2 + 0x04], %%g2 + addxcc %%g3, %%g4, %%g4 + ld [%2 + 0x00], %%g3 + addxcc %%g2, %%g4, %%g4 + ld [%1 + 0x0c], %%g2 + addxcc %%g3, %%g4, %%g4 + ld [%1 + 0x08], %%g3 + addxcc %%g2, %%g4, %%g4 + ld [%1 + 0x04], %%g2 + addxcc %%g3, %%g4, %%g4 + ld [%1 + 0x00], %%g3 + addxcc %%g2, %%g4, %%g4 + addxcc %%g3, %%g4, %0 + addx 0, %0, %0 + " + : "=&r" (sum) + : "r" (saddr), "r" (daddr), + "r"(htonl((__u32) (len))), "r"(htonl(proto)), "r"(sum) + : "g2", "g3", "g4"); + + return csum_fold(sum); +} + +/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */ +extern __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#endif /* !(__SPARC_CHECKSUM_H) */ diff --git a/include/asm-sparc/clock.h b/include/asm-sparc/clock.h index ce5ce6762..e708e6b50 100644 --- a/include/asm-sparc/clock.h +++ b/include/asm-sparc/clock.h @@ -1,53 +1,11 @@ -/* clock.h: Definitions for the clock/timer chips on the Sparc. +/* $Id: clock.h,v 1.3 1995/11/25 02:31:25 davem Exp $ + * clock.h: Definitions for clock operations on the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#ifndef _SPARC_CLOCK_H +#define _SPARC_CLOCK_H -/* Clock timer structures. The interrupt timer has two properties which - * are the counter (which is handled in do_timer in sched.c) and the limit. - * This limit is where the timer's counter 'wraps' around. Oddly enough, - * the sun4c timer when it hits the limit wraps back to 1 and not zero - * thus when calculating the value at which it will fire a microsecond you - * must adjust by one. Thanks SUN for designing such great hardware ;( - */ - -/* Note that I am only going to use the timer that interrupts at - * Sparc IRQ 10. There is another one available that can fire at - * IRQ 14. If I can think of some creative uses for it this may - * change. It might make a nice kernel/user profiler etc. - */ - -struct sparc_timer_info { - unsigned int cur_count10; - unsigned int timer_limit10; - unsigned int cur_count14; - unsigned int timer_limit14; -}; - -struct sparc_clock_info { - unsigned char hsec; - unsigned char hr; - unsigned char min; - unsigned char sec; - unsigned char mon; - unsigned char day; - unsigned char yr; - unsigned char wkday; - unsigned char ram_hsec; - unsigned char ram_hr; - unsigned char ram_min; - unsigned char ram_sec; - unsigned char ram_mon; - unsigned char ram_day; - unsigned char ram_year; - unsigned char ram_wkday; - unsigned char intr_reg; - unsigned char cmd_reg; - unsigned char foo[14]; -}; - -#define TIMER_PHYSADDR 0xf3000000 - -/* YUCK YUCK YUCK, grrr... */ -#define TIMER_STRUCT ((struct sparc_timer_info *)((struct sparc_clock_info *) TIMER_VADDR)) +/* Foo for now. */ +#endif /* !(_SPARC_CLOCK_H) */ diff --git a/include/asm-sparc/contregs.h b/include/asm-sparc/contregs.h index 326e888ff..adf4718a2 100644 --- a/include/asm-sparc/contregs.h +++ b/include/asm-sparc/contregs.h @@ -1,19 +1,50 @@ +/* $Id: contregs.h,v 1.6 1995/11/25 02:31:27 davem Exp $ */ #ifndef _SPARC_CONTREGS_H #define _SPARC_CONTREGS_H /* contregs.h: Addresses of registers in the ASI_CONTROL alternate address - space. These are for the mmu's context register, etc. + * space. These are for the mmu's context register, etc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ +/* 4=sun4 (as in sun4 sysmaint student book), c=sun4c (according to davem) */ -#define AC_CONTEXT 0x30000000 /* current mmu-context, handy for invalidate()'s ;-) */ -#define AC_SENABLE 0x40000000 /* system dvma/cache enable, plus special reset poking */ -#define AC_CACHETAGS 0x80000000 /* direct access to the VAC cache, unused... */ -#define AC_SYNC_ERR 0x60000000 /* what type of synchronous memory error happened */ -#define AC_SYNC_VA 0x60000004 /* what virtual address caused the error to occur */ -#define AC_ASYNC_ERR 0x60000008 /* what type of asynchronous mem-error happened */ -#define AC_ASYNC_VA 0x6000000c /* what virtual address caused the async-err to happen */ -#define AC_CACHEDDATA 0x90000000 /* where the actual VAC cached data sits */ +#define AC_IDPROM 0x00000000 /* 4 ID PROM, R/O, byte, 32 bytes */ +#define AC_CONTEXT 0x30000000 /* 4c current mmu-context */ +#define AC_SENABLE 0x40000000 /* 4c system dvma/cache/reset enable reg */ +#define AC_UDVMA_ENB 0x50000000 /* 4 Not used on Sun boards, byte */ +#define AC_BUS_ERROR 0x60000000 /* 4 Cleared on read, byte. */ +#define AC_SYNC_ERR 0x60000000 /* c fault type */ +#define AC_SYNC_VA 0x60000004 /* c fault virtual address */ +#define AC_ASYNC_ERR 0x60000008 /* c asynchronous fault type */ +#define AC_ASYNC_VA 0x6000000c /* c async fault virtual address */ +#define AC_LEDS 0x70000000 /* 4 Zero turns on LEDs, byte */ +#define AC_CACHETAGS 0x80000000 /* 4c direct access to the VAC tags */ +#define AC_CACHEDDATA 0x90000000 /* c direct access to the VAC data */ +#define AC_UDVMA_MAP 0xD0000000 /* 4 Not used on Sun boards, byte */ +#define AC_VME_VECTOR 0xE0000000 /* 4 For non-Autovector VME, byte */ +#define AC_BOOT_SCC 0xF0000000 /* 4 bypass to access Zilog 8530. byte. */ + +/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */ +#define AC_M_PCR 0x0000 /* shv Processor Control Reg */ +#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */ +#define AC_M_CXR 0x0200 /* shv Context Register */ +#define AC_M_SFSR 0x0300 /* shv Synchronous Fault Status Reg */ +#define AC_M_SFAR 0x0400 /* shv Synchronous Fault Address Reg */ +#define AC_M_AFSR 0x0500 /* hv Asynchronous Fault Status Reg */ +#define AC_M_AFAR 0x0600 /* hv Asynchronous Fault Address Reg */ +#define AC_M_RESET 0x0700 /* hv Reset Reg */ +#define AC_M_RPR 0x1000 /* hv Root Pointer Reg */ +#define AC_M_TSUTRCR 0x1000 /* s TLB Replacement Ctrl Reg */ +#define AC_M_IAPTP 0x1100 /* hv Instruction Access PTP */ +#define AC_M_DAPTP 0x1200 /* hv Data Access PTP */ +#define AC_M_ITR 0x1300 /* hv Index Tag Register */ +#define AC_M_TRCR 0x1400 /* hv TLB Replacement Control Reg */ +#define AC_M_SFSRX 0x1300 /* s Synch Fault Status Reg prim */ +#define AC_M_SFARX 0x1400 /* s Synch Fault Address Reg prim */ +#define AC_M_RPR1 0x1500 /* h Root Pointer Reg (entry 2) */ +#define AC_M_IAPTP1 0x1600 /* h Instruction Access PTP (entry 2) */ +#define AC_M_DAPTP1 0x1700 /* h Data Access PTP (entry 2) */ #endif /* _SPARC_CONTREGS_H */ diff --git a/include/asm-sparc/cprefix.h b/include/asm-sparc/cprefix.h index 439c7c671..61cde329a 100644 --- a/include/asm-sparc/cprefix.h +++ b/include/asm-sparc/cprefix.h @@ -6,15 +6,18 @@ * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#ifndef __SPARC_CPREFIX_H +#define __SPARC_CPREFIX_H - -#ifndef __svr4__ -#define C_LABEL_PREFIX _ -#else +#if defined(__svr4__) || defined(__ELF__) #define C_LABEL_PREFIX +#else +#define C_LABEL_PREFIX _ #endif -#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a##b -#define C_LABEL(name) CONCAT1(C_LABEL_PREFIX, name) +#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name) + +#endif /* !(__SPARC_CPREFIX_H) */ diff --git a/include/asm-sparc/cypress.h b/include/asm-sparc/cypress.h new file mode 100644 index 000000000..fc92fc839 --- /dev/null +++ b/include/asm-sparc/cypress.h @@ -0,0 +1,79 @@ +/* $Id: cypress.h,v 1.6 1996/08/29 09:48:09 davem Exp $ + * cypress.h: Cypress module specific definitions and defines. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_CYPRESS_H +#define _SPARC_CYPRESS_H + +/* Cypress chips have %psr 'impl' of '0001' and 'vers' of '0001'. */ + +/* The MMU control register fields on the Sparc Cypress 604/605 MMU's. + * + * --------------------------------------------------------------- + * |implvers| MCA | MCM |MV| MID |BM| C|RSV|MR|CM|CL|CE|RSV|NF|ME| + * --------------------------------------------------------------- + * 31 24 23-22 21-20 19 18-15 14 13 12 11 10 9 8 7-2 1 0 + * + * MCA: MultiChip Access -- Used for configuration of multiple + * CY7C604/605 cache units. + * MCM: MultiChip Mask -- Again, for multiple cache unit config. + * MV: MultiChip Valid -- Indicates MCM and MCA have valid settings. + * MID: ModuleID -- Unique processor ID for MBus transactions. (605 only) + * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode + * C: Cacheable -- Indicates whether accesses are cacheable while + * the MMU is off. 0=no 1=yes + * MR: MemoryReflection -- Indicates whether the bus attached to the + * MBus supports memory reflection. 0=no 1=yes (605 only) + * CM: CacheMode -- Indicates whether the cache is operating in write + * through or copy-back mode. 0=write-through 1=copy-back + * CL: CacheLock -- Indicates if the entire cache is locked or not. + * 0=not-locked 1=locked (604 only) + * CE: CacheEnable -- Is the virtual cache on? 0=no 1=yes + * NF: NoFault -- Do faults generate traps? 0=yes 1=no + * ME: MmuEnable -- Is the MMU doing translations? 0=no 1=yes + */ + +#define CYPRESS_MCA 0x00c00000 +#define CYPRESS_MCM 0x00300000 +#define CYPRESS_MVALID 0x00080000 +#define CYPRESS_MIDMASK 0x00078000 /* Only on 605 */ +#define CYPRESS_BMODE 0x00004000 +#define CYPRESS_ACENABLE 0x00002000 +#define CYPRESS_MRFLCT 0x00000800 /* Only on 605 */ +#define CYPRESS_CMODE 0x00000400 +#define CYPRESS_CLOCK 0x00000200 /* Only on 604 */ +#define CYPRESS_CENABLE 0x00000100 +#define CYPRESS_NFAULT 0x00000002 +#define CYPRESS_MENABLE 0x00000001 + +extern __inline__ void cypress_flush_page(unsigned long page) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (page), "i" (ASI_M_FLUSH_PAGE)); +} + +extern __inline__ void cypress_flush_segment(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_SEG)); +} + +extern __inline__ void cypress_flush_region(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_REGION)); +} + +extern __inline__ void cypress_flush_context(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_FLUSH_CTX)); +} + +/* XXX Displacement flushes for buggy chips and initial testing + * XXX go here. + */ + +#endif /* !(_SPARC_CYPRESS_H) */ diff --git a/include/asm-sparc/delay.h b/include/asm-sparc/delay.h index d6c4b360e..71e1154a0 100644 --- a/include/asm-sparc/delay.h +++ b/include/asm-sparc/delay.h @@ -1,40 +1,28 @@ +/* $Id: delay.h,v 1.8 1996/01/28 02:09:21 davem Exp $ + * delay.h: Linux delay routines on the Sparc. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu). + */ + #ifndef __SPARC_DELAY_H #define __SPARC_DELAY_H extern unsigned long loops_per_sec; -/* - * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu). - * - * Delay quick inlined code using 'loops_per_second' which is - * calculated in calibrate_delay() in main.c (ie. BogoMIPS :-) - */ - -extern __inline__ void __delay(unsigned int loops) +extern __inline__ void __delay(unsigned long loops) { - __asm__ __volatile__("\n1:\tcmp %0, 0\n\t" - "bne,a 1b\n\t" - "sub %0, 1, %0\n": "=&r" (loops) : "0" (loops)); + __asm__ __volatile__("cmp %0, 0\n\t" + "1: bne 1b\n\t" + "subcc %0, 1, %0\n" : + "=&r" (loops) : + "0" (loops)); } -/* udelay(usecs) is used for very short delays up to 1 millisecond. */ - -extern __inline__ void udelay(unsigned int usecs) -{ - usecs *= 0x000010c6; /* Sparc is 32-bit just like ix86 */ - - __asm__("sethi %hi(_loops_per_sec), %o1\n\t" - "ld [%o1 + %lo(_loops_per_sec)], %o1\n\t" - "call ___delay\n\t" - "umul %o1, %o0, %o0\n\t"); -} +/* This is too messy with inline asm on the Sparc. */ +extern void udelay(unsigned long usecs); /* calibrate_delay() wants this... */ - -extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) -{ - return ((a*b)/c); -} +#define muldiv(a, b, c) (((a)*(b))/(c)) #endif /* defined(__SPARC_DELAY_H) */ diff --git a/include/asm-sparc/dma.h b/include/asm-sparc/dma.h index 138e7a445..a86379a71 100644 --- a/include/asm-sparc/dma.h +++ b/include/asm-sparc/dma.h @@ -1,20 +1,209 @@ -/* +/* $Id: dma.h,v 1.22 1996/10/17 05:29:01 davem Exp $ * include/asm-sparc/dma.h * - * Don't even ask, I am figuring out how this crap works - * on the Sparc. It may end up being real hairy to plug - * into this code, maybe not, we'll see. - * - * Copyright (C) David S. Miller (davem@caip.rutgers.edu) + * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu) */ +#ifndef _ASM_SPARC_DMA_H +#define _ASM_SPARC_DMA_H + +#include <linux/kernel.h> + #include <asm/vac-ops.h> /* for invalidate's, etc. */ +#include <asm/sbus.h> +#include <asm/delay.h> +#include <asm/oplib.h> +/* These are irrelevant for Sparc DMA, but we leave it in so that + * things can compile. + */ #define MAX_DMA_CHANNELS 8 -#define MAX_DMA_ADDRESS 0x0 +#define MAX_DMA_ADDRESS (~0UL) +#define DMA_MODE_READ 1 +#define DMA_MODE_WRITE 2 -#ifndef _ASM_SPARC_DMA_H -#define _ASM_SPARC_DMA_H +/* Useful constants */ +#define SIZE_16MB (16*1024*1024) +#define SIZE_64K (64*1024) + +/* Structure to describe the current status of DMA registers on the Sparc */ +struct sparc_dma_registers { + __volatile__ unsigned long cond_reg; /* DMA condition register */ + __volatile__ char * st_addr; /* Start address of this transfer */ + __volatile__ unsigned long cnt; /* How many bytes to transfer */ + __volatile__ unsigned long dma_test; /* DMA test register */ +}; + +/* DVMA chip revisions */ +enum dvma_rev { + dvmarev0, + dvmaesc1, + dvmarev1, + dvmarev2, + dvmarev3, + dvmarevplus, + dvmahme +}; + +#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) + +/* Linux DMA information structure, filled during probe. */ +struct Linux_SBus_DMA { + struct Linux_SBus_DMA *next; + struct linux_sbus_device *SBus_dev; + struct sparc_dma_registers *regs; + + /* Status, misc info */ + int node; /* Prom node for this DMA device */ + int running; /* Are we doing DMA now? */ + int allocated; /* Are we "owned" by anyone yet? */ + + /* Transfer information. */ + unsigned long addr; /* Start address of current transfer */ + int nbytes; /* Size of current transfer */ + int realbytes; /* For splitting up large transfers, etc. */ + + /* DMA revision */ + enum dvma_rev revision; +}; + +extern struct Linux_SBus_DMA *dma_chain; + +/* Broken hardware... */ +#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1) +#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) + +/* Main routines in dma.c */ +extern void dump_dma_regs(struct sparc_dma_registers *); +extern unsigned long dvma_init(struct linux_sbus *, unsigned long); + +/* Fields in the cond_reg register */ +/* First, the version identification bits */ +#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ +#define DMA_VERS0 0x00000000 /* Sunray DMA version */ +#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ +#define DMA_VERS1 0x80000000 /* DMA rev 1 */ +#define DMA_VERS2 0xa0000000 /* DMA rev 2 */ +#define DMA_VERHME 0xb0000000 /* DMA hme gate array */ +#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ + +#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ +#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ +#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ +#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ +#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ +#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ +#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ +#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ +#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ +#define DMA_ST_WRITE 0x00000100 /* write from device to memory */ +#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ +#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ +#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ +#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ +#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ +#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ +#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ +#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ +#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ +#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ +#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ +#define DMA_E_BURST8 0x00040000 /* ENET: SBUS r/w burst size */ +#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ +#define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ +#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ +#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ +#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ +#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ +#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ +#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ +#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ +#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ +#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ +#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ +#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ +#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ +#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ + +/* Values describing the burst-size property from the PROM */ +#define DMA_BURST1 0x01 +#define DMA_BURST2 0x02 +#define DMA_BURST4 0x04 +#define DMA_BURST8 0x08 +#define DMA_BURST16 0x10 +#define DMA_BURST32 0x20 +#define DMA_BURST64 0x40 +#define DMA_BURSTBITS 0x7f + +/* Determine highest possible final transfer address given a base */ +#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) + +/* Yes, I hack a lot of elisp in my spare time... */ +#define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR)) +#define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))) +#define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE)) +#define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE))) +#define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB))) +#define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB))) +#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV)) +#define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr)) +#define DMA_BEGINDMA_W(regs) \ + ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB)))) +#define DMA_BEGINDMA_R(regs) \ + ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE))))) + +/* For certain DMA chips, we need to disable ints upon irq entry + * and turn them back on when we are done. So in any ESP interrupt + * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT + * when leaving the handler. You have been warned... + */ +#define DMA_IRQ_ENTRY(dma, dregs) do { \ + if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ + } while (0) + +#define DMA_IRQ_EXIT(dma, dregs) do { \ + if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ + } while(0) + +/* Pause until counter runs out or BIT isn't set in the DMA condition + * register. + */ +extern __inline__ void sparc_dma_pause(struct sparc_dma_registers *regs, + unsigned long bit) +{ + int ctr = 50000; /* Let's find some bugs ;) */ + + /* Busy wait until the bit is not set any more */ + while((regs->cond_reg&bit) && (ctr>0)) { + ctr--; + __delay(5); + } + + /* Check for bogus outcome. */ + if(!ctr) + panic("DMA timeout"); +} + +/* Reset the friggin' thing... */ +#define DMA_RESET(dma) do { \ + struct sparc_dma_registers *regs = dma->regs; \ + /* Let the current FIFO drain itself */ \ + sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \ + /* Reset the logic */ \ + regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \ + __delay(400); /* let the bits set ;) */ \ + regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \ + sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \ + /* Enable FAST transfers if available */ \ + if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \ + dma->running = 0; \ +} while(0) + +#define for_each_dvma(dma) \ + for((dma) = dma_chain; (dma); (dma) = (dma)->next) +extern int get_dma_list(char *); +extern int request_dma(unsigned int, __const__ char *); +extern void free_dma(unsigned int); #endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/include/asm-sparc/ecc.h b/include/asm-sparc/ecc.h new file mode 100644 index 000000000..8e27ceccb --- /dev/null +++ b/include/asm-sparc/ecc.h @@ -0,0 +1,122 @@ +/* $Id: ecc.h,v 1.3 1996/04/25 06:12:57 davem Exp $ + * ecc.h: Definitions and defines for the external cache/memory + * controller on the sun4m. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_ECC_H +#define _SPARC_ECC_H + +/* These registers are accessed through the SRMMU passthrough ASI 0x20 */ +#define ECC_ENABLE 0x00000000 /* ECC enable register */ +#define ECC_FSTATUS 0x00000008 /* ECC fault status register */ +#define ECC_FADDR 0x00000010 /* ECC fault address register */ +#define ECC_DIGNOSTIC 0x00000018 /* ECC diagnostics register */ +#define ECC_MBAENAB 0x00000020 /* MBus arbiter enable register */ +#define ECC_DMESG 0x00001000 /* Diagnostic message passing area */ + +/* ECC MBus Arbiter Enable register: + * + * ---------------------------------------- + * | |SBUS|MOD3|MOD2|MOD1|RSV| + * ---------------------------------------- + * 31 5 4 3 2 1 0 + * + * SBUS: Enable MBus Arbiter on the SBus 0=off 1=on + * MOD3: Enable MBus Arbiter on MBus module 3 0=off 1=on + * MOD2: Enable MBus Arbiter on MBus module 2 0=off 1=on + * MOD1: Enable MBus Arbiter on MBus module 1 0=off 1=on + */ + +#define ECC_MBAE_SBUS 0x00000010 +#define ECC_MBAE_MOD3 0x00000008 +#define ECC_MBAE_MOD2 0x00000004 +#define ECC_MBAE_MOD1 0x00000002 + +/* ECC Fault Control Register layout: + * + * ----------------------------- + * | RESV | ECHECK | EINT | + * ----------------------------- + * 31 2 1 0 + * + * ECHECK: Enable ECC checking. 0=off 1=on + * EINT: Enable Interrupts for correctable errors. 0=off 1=on + */ +#define ECC_FCR_CHECK 0x00000002 +#define ECC_FCR_INTENAB 0x00000001 + +/* ECC Fault Address Register Zero layout: + * + * ----------------------------------------------------- + * | MID | S | RSV | VA | BM |AT| C| SZ |TYP| PADDR | + * ----------------------------------------------------- + * 31-28 27 26-22 21-14 13 12 11 10-8 7-4 3-0 + * + * MID: ModuleID of the faulting processor. ie. who did it? + * S: Supervisor/Privileged access? 0=no 1=yes + * VA: Bits 19-12 of the virtual faulting address, these are the + * superset bits in the virtual cache and can be used for + * a flush operation if necessary. + * BM: Boot mode? 0=no 1=yes This is just like the SRMMU boot + * mode bit. + * AT: Did this fault happen during an atomic instruction? 0=no + * 1=yes. This means either an 'ldstub' or 'swap' instruction + * was in progress (but not finished) when this fault happened. + * This indicated whether the bus was locked when the fault + * occurred. + * C: Did the pte for this access indicate that it was cacheable? + * 0=no 1=yes + * SZ: The size of the transaction. + * TYP: The transaction type. + * PADDR: Bits 35-32 of the physical address for the fault. + */ +#define ECC_FADDR0_MIDMASK 0xf0000000 +#define ECC_FADDR0_S 0x08000000 +#define ECC_FADDR0_VADDR 0x003fc000 +#define ECC_FADDR0_BMODE 0x00002000 +#define ECC_FADDR0_ATOMIC 0x00001000 +#define ECC_FADDR0_CACHE 0x00000800 +#define ECC_FADDR0_SIZE 0x00000700 +#define ECC_FADDR0_TYPE 0x000000f0 +#define ECC_FADDR0_PADDR 0x0000000f + +/* ECC Fault Address Register One layout: + * + * ------------------------------------- + * | Physical Address 31-0 | + * ------------------------------------- + * 31 0 + * + * You get the upper 4 bits of the physical address from the + * PADDR field in ECC Fault Address Zero register. + */ + +/* ECC Fault Status Register layout: + * + * ---------------------------------------------- + * | RESV|C2E|MULT|SYNDROME|DWORD|UNC|TIMEO|BS|C| + * ---------------------------------------------- + * 31-18 17 16 15-8 7-4 3 2 1 0 + * + * C2E: A C2 graphics error occurred. 0=no 1=yes (SS10 only) + * MULT: Multiple errors occurred ;-O 0=no 1=prom_panic(yes) + * SYNDROME: Controller is mentally unstable. + * DWORD: + * UNC: Uncorrectable error. 0=no 1=yes + * TIMEO: Timeout occurred. 0=no 1=yes + * BS: C2 graphics bad slot access. 0=no 1=yes (SS10 only) + * C: Correctable error? 0=no 1=yes + */ + +#define ECC_FSR_C2ERR 0x00020000 +#define ECC_FSR_MULT 0x00010000 +#define ECC_FSR_SYND 0x0000ff00 +#define ECC_FSR_DWORD 0x000000f0 +#define ECC_FSR_UNC 0x00000008 +#define ECC_FSR_TIMEO 0x00000004 +#define ECC_FSR_BADSLOT 0x00000002 +#define ECC_FSR_C 0x00000001 + +#endif /* !(_SPARC_ECC_H) */ diff --git a/include/asm-sparc/eeprom.h b/include/asm-sparc/eeprom.h new file mode 100644 index 000000000..a8ff7496d --- /dev/null +++ b/include/asm-sparc/eeprom.h @@ -0,0 +1,9 @@ +/* $Id: eeprom.h,v 1.3 1995/11/25 02:31:38 davem Exp $ + * eeprom.h: Definitions for the Sun eeprom. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +/* The EEPROM and the Mostek Mk48t02 use the same IO address space + * for their registers/data areas. The IDPROM lives here too. + */ diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h new file mode 100644 index 000000000..46cd67f37 --- /dev/null +++ b/include/asm-sparc/elf.h @@ -0,0 +1,34 @@ +/* $Id: elf.h,v 1.5 1996/08/08 00:06:13 ecd Exp $ */ +#ifndef __ASMSPARC_ELF_H +#define __ASMSPARC_ELF_H + +/* + * ELF register definitions.. + */ + +#include <asm/ptrace.h> + +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef unsigned long elf_fpregset_t; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x) == EM_SPARC) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_ARCH EM_SPARC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB; + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + + +#endif /* !(__ASMSPARC_ELF_H) */ diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h new file mode 100644 index 000000000..3348a3833 --- /dev/null +++ b/include/asm-sparc/errno.h @@ -0,0 +1,133 @@ +/* $Id: errno.h,v 1.5 1996/07/13 02:05:13 tridge Exp $ */ +#ifndef _SPARC_ERRNO_H +#define _SPARC_ERRNO_H + +/* These match the SunOS error numbering scheme. */ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Op not supported on transport endpoint */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Cannot assign requested address */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Net dropped connection because of reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Transport endpoint is already connected */ +#define ENOTCONN 57 /* Transport endpoint is not connected */ +#define ESHUTDOWN 58 /* No send after transport endpoint shutdown */ +#define ETOOMANYREFS 59 /* Too many references: cannot splice */ +#define ETIMEDOUT 60 /* Connection timed out */ +#define ECONNREFUSED 61 /* Connection refused */ +#define ELOOP 62 /* Too many symbolic links encountered */ +#define ENAMETOOLONG 63 /* File name too long */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ +#define EPROCLIM 67 /* SUNOS: Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Quota exceeded */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Object is remote */ +#define ENOSTR 72 /* Device not a stream */ +#define ETIME 73 /* Timer expired */ +#define ENOSR 74 /* Out of streams resources */ +#define ENOMSG 75 /* No message of desired type */ +#define EBADMSG 76 /* Not a data message */ +#define EIDRM 77 /* Identifier removed */ +#define EDEADLK 78 /* Resource deadlock would occur */ +#define ENOLCK 79 /* No record locks available */ +#define ENONET 80 /* Machine is not on the network */ +#define ERREMOTE 81 /* SunOS: Too many lvls of remote in path */ +#define ENOLINK 82 /* Link has been severed */ +#define EADV 83 /* Advertise error */ +#define ESRMNT 84 /* Srmount error */ +#define ECOMM 85 /* Communication error on send */ +#define EPROTO 86 /* Protocol error */ +#define EMULTIHOP 87 /* Multihop attempted */ +#define EDOTDOT 88 /* RFS specific error */ +#define EREMCHG 89 /* Remote address changed */ +#define ENOSYS 90 /* Function not implemented */ + +/* The rest have no SunOS equivalent. */ +#define ESTRPIPE 91 /* Streams pipe error */ +#define EOVERFLOW 92 /* Value too large for defined data type */ +#define EBADFD 93 /* File descriptor in bad state */ +#define ECHRNG 94 /* Channel number out of range */ +#define EL2NSYNC 95 /* Level 2 not synchronized */ +#define EL3HLT 96 /* Level 3 halted */ +#define EL3RST 97 /* Level 3 reset */ +#define ELNRNG 98 /* Link number out of range */ +#define EUNATCH 99 /* Protocol driver not attached */ +#define ENOCSI 100 /* No CSI structure available */ +#define EL2HLT 101 /* Level 2 halted */ +#define EBADE 102 /* Invalid exchange */ +#define EBADR 103 /* Invalid request descriptor */ +#define EXFULL 104 /* Exchange full */ +#define ENOANO 105 /* No anode */ +#define EBADRQC 106 /* Invalid request code */ +#define EBADSLT 107 /* Invalid slot */ +#define EDEADLOCK 108 /* File locking deadlock error */ +#define EBFONT 109 /* Bad font file format */ +#define ELIBEXEC 110 /* Cannot exec a shared library directly */ +#define ENODATA 111 /* No data available */ +#define ELIBBAD 112 /* Accessing a corrupted shared library */ +#define ENOPKG 113 /* Package not installed */ +#define ELIBACC 114 /* Can not access a needed shared library */ +#define ENOTUNIQ 115 /* Name not unique on network */ +#define ERESTART 116 /* Interrupted syscall should be restarted */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EILSEQ 122 /* Illegal byte sequence */ +#define ELIBMAX 123 /* Atmpt to link in too many shared libs */ +#define ELIBSCN 124 /* .lib section in a.out corrupted */ + +#endif diff --git a/include/asm-sparc/fbio.h b/include/asm-sparc/fbio.h new file mode 100644 index 000000000..b7eb21003 --- /dev/null +++ b/include/asm-sparc/fbio.h @@ -0,0 +1,279 @@ +#ifndef __LINUX_FBIO_H +#define __LINUX_FBIO_H + +/* Constants used for fbio SunOS compatibility */ +/* (C) 1996 Miguel de Icaza */ + +/* Frame buffer types */ +#define FBTYPE_NOTYPE -1 +#define FBTYPE_SUN1BW 0 /* mono */ +#define FBTYPE_SUN1COLOR 1 +#define FBTYPE_SUN2BW 2 +#define FBTYPE_SUN2COLOR 3 +#define FBTYPE_SUN2GP 4 +#define FBTYPE_SUN5COLOR 5 +#define FBTYPE_SUN3COLOR 6 +#define FBTYPE_MEMCOLOR 7 +#define FBTYPE_SUN4COLOR 8 + +#define FBTYPE_NOTSUN1 9 +#define FBTYPE_NOTSUN2 10 +#define FBTYPE_NOTSUN3 11 + +#define FBTYPE_SUNFAST_COLOR 12 /* cg6 */ +#define FBTYPE_SUNROP_COLOR 13 +#define FBTYPE_SUNFB_VIDEO 14 +#define FBTYPE_SUNGIFB 15 +#define FBTYPE_SUNGPLAS 16 +#define FBTYPE_SUNGP3 17 +#define FBTYPE_SUNGT 18 +#define FBTYPE_SUNLEO 19 /* zx Leo card */ +#define FBTYPE_MDICOLOR 20 /* cg14 */ +#define FBTYPE_TCXCOLOR 21 /* SUNW,tcx card */ + +#define FBTYPE_LASTPLUSONE 21 /* This is not last + 1 in fact... */ + +/* fbio ioctls */ +/* Returned by FBIOGTYPE */ +struct fbtype { + int fb_type; /* fb type, see above */ + int fb_height; /* pixels */ + int fb_width; /* pixels */ + int fb_depth; + int fb_cmsize; /* color map entries */ + int fb_size; /* fb size in bytes */ +}; +#define FBIOGTYPE _IOR('F', 0, struct fbtype) + +/* Used by FBIOPUTCMAP */ +struct fbcmap { + int index; /* first element (0 origin) */ + int count; + unsigned char *red; + unsigned char *green; + unsigned char *blue; +}; + +#define FBIOPUTCMAP _IOW('F', 3, struct fbcmap) +#define FBIOGETCMAP _IOW('F', 4, struct fbcmap) + +/* # of device specific values */ +#define FB_ATTR_NDEVSPECIFIC 8 +/* # of possible emulations */ +#define FB_ATTR_NEMUTYPES 4 + +struct fbsattr { + int flags; + int emu_type; /* -1 if none */ + int dev_specific[FB_ATTR_NDEVSPECIFIC]; +}; + +struct fbgattr { + int real_type; /* real frame buffer type */ + int owner; /* unknown */ + struct fbtype fbtype; /* real frame buffer fbtype */ + struct fbsattr sattr; + int emu_types[FB_ATTR_NEMUTYPES]; /* supported emulations */ +}; +#define FBIOSATTR _IOW('F', 5, struct fbgattr) /* Unsupported: */ +#define FBIOGATTR _IOR('F', 6, struct fbgattr) /* supported */ + +#define FBIOSVIDEO _IOW('F', 7, int) +#define FBIOGVIDEO _IOR('F', 8, int) + +/* Cursor position */ +struct fbcurpos { +#ifdef __KERNEL__ + short fbx, fby; +#else + short x, y; +#endif +}; + +/* Cursor operations */ +#define FB_CUR_SETCUR 0x01 /* Enable/disable cursor display */ +#define FB_CUR_SETPOS 0x02 /* set cursor position */ +#define FB_CUR_SETHOT 0x04 /* set cursor hotspot */ +#define FB_CUR_SETCMAP 0x08 /* set color map for the cursor */ +#define FB_CUR_SETSHAPE 0x10 /* set shape */ +#define FB_CUR_SETALL 0x1F /* all of the above */ + +struct fbcursor { + short set; /* what to set, choose from the list above */ + short enable; /* cursor on/off */ + struct fbcurpos pos; /* cursor position */ + struct fbcurpos hot; /* cursor hot spot */ + struct fbcmap cmap; /* color map info */ + struct fbcurpos size; /* cursor bit map size */ + char *image; /* cursor image bits */ + char *mask; /* cursor mask bits */ +}; + +/* set/get cursor attributes/shape */ +#define FBIOSCURSOR _IOW('F', 24, struct fbcursor) +#define FBIOGCURSOR _IOWR('F', 25, struct fbcursor) + +/* set/get cursor position */ +#define FBIOSCURPOS _IOW('F', 26, struct fbcurpos) +#define FBIOGCURPOS _IOW('F', 27, struct fbcurpos) + +/* get max cursor size */ +#define FBIOGCURMAX _IOR('F', 28, struct fbcurpos) + +/* wid manipulation */ +struct fb_wid_alloc { +#define FB_WID_SHARED_8 0 +#define FB_WID_SHARED_24 1 +#define FB_WID_DBL_8 2 +#define FB_WID_DBL_24 3 + __u32 wa_type; + __s32 wa_index; /* Set on return */ + __u32 wa_count; +}; +struct fb_wid_item { + __u32 wi_type; + __s32 wi_index; + __u32 wi_attrs; + __u32 wi_values[32]; +}; +struct fb_wid_list { + __u32 wl_flags; + __u32 wl_count; + struct fb_wid_item *wl_list; +}; + +#define FBIO_WID_ALLOC _IOWR('F', 30, struct fb_wid_alloc) +#define FBIO_WID_FREE _IOW('F', 31, struct fb_wid_alloc) +#define FBIO_WID_PUT _IOW('F', 32, struct fb_wid_list) +#define FBIO_WID_GET _IOWR('F', 33, struct fb_wid_list) + +/* Cg14 ioctls */ +#define MDI_IOCTL ('M'<<8) +#define MDI_RESET (MDI_IOCTL|1) +#define MDI_GET_CFGINFO (MDI_IOCTL|2) +#define MDI_SET_PIXELMODE (MDI_IOCTL|3) +# define MDI_32_PIX 32 +# define MDI_16_PIX 16 +# define MDI_8_PIX 8 + +struct mdi_cfginfo { + int mdi_ncluts; /* Number of implemented CLUTs in this MDI */ + int mdi_type; /* FBTYPE name */ + int mdi_height; /* height */ + int mdi_width; /* widht */ + int mdi_size; /* available ram */ + int mdi_mode; /* 8bpp, 16bpp or 32bpp */ + int mdi_pixfreq; /* pixel clock (from PROM) */ +}; + +/* SparcLinux specific ioctl for the MDI, should be replaced for + * the SET_XLUT/SET_CLUTn ioctls instead + */ +#define MDI_CLEAR_XLUT (MDI_IOCTL|9) + +/* leo ioctls */ +struct leo_clut_alloc { + __u32 clutid; /* Set on return */ + __u32 flag; + __u32 index; +}; + +struct leo_clut { +#define LEO_CLUT_WAIT 0x00000001 /* Not yet implemented */ + __u32 flag; + __u32 clutid; + __u32 offset; + __u32 count; + char * red; + char * green; + char * blue; +}; +#define LEO_CLUTALLOC _IOWR('L', 53, struct leo_clut_alloc) +#define LEO_CLUTFREE _IOW('L', 54, struct leo_clut_alloc) +#define LEO_CLUTREAD _IOW('L', 55, struct leo_clut) +#define LEO_CLUTPOST _IOW('L', 56, struct leo_clut) +#define LEO_SETGAMMA _IOW('L', 68, int) /* Not yet implemented */ +#define LEO_GETGAMMA _IOR('L', 69, int) /* Not yet implemented */ + +#ifdef __KERNEL__ +/* Addresses on the fd of a cgsix that are mappable */ +#define CG6_FBC 0x70000000 +#define CG6_TEC 0x70001000 +#define CG6_BTREGS 0x70002000 +#define CG6_FHC 0x70004000 +#define CG6_THC 0x70005000 +#define CG6_ROM 0x70006000 +#define CG6_RAM 0x70016000 +#define CG6_DHC 0x80000000 + +#define CG3_MMAP_OFFSET 0x4000000 + +/* Addresses on the fd of a tcx that are mappable */ +#define TCX_RAM8BIT 0x00000000 +#define TCX_RAM24BIT 0x01000000 +#define TCX_UNK3 0x10000000 +#define TCX_UNK4 0x20000000 +#define TCX_CONTROLPLANE 0x28000000 +#define TCX_UNK6 0x30000000 +#define TCX_UNK7 0x38000000 +#define TCX_TEC 0x70000000 +#define TCX_BTREGS 0x70002000 +#define TCX_THC 0x70004000 +#define TCX_DHC 0x70008000 +#define TCX_ALT 0x7000a000 +#define TCX_SYNC 0x7000e000 +#define TCX_UNK2 0x70010000 + +/* CG14 definitions */ + +/* Offsets into the OBIO space: */ +#define CG14_REGS 0 /* registers */ +#define CG14_CURSORREGS 0x1000 /* cursor registers */ +#define CG14_DACREGS 0x2000 /* DAC registers */ +#define CG14_XLUT 0x3000 /* X Look Up Table -- ??? */ +#define CG14_CLUT1 0x4000 /* Color Look Up Table */ +#define CG14_CLUT2 0x5000 /* Color Look Up Table */ +#define CG14_CLUT3 0x6000 /* Color Look Up Table */ +#define CG14_AUTO 0xf000 + +#endif /* KERNEL */ + +/* These are exported to userland for applications to use */ +/* Mappable offsets for the cg14: control registers */ +#define MDI_DIRECT_MAP 0x10000000 +#define MDI_CTLREG_MAP 0x20000000 +#define MDI_CURSOR_MAP 0x30000000 +#define MDI_SHDW_VRT_MAP 0x40000000 + +/* Mappable offsets for the cg14: frame buffer resolutions */ +/* 32 bits */ +#define MDI_CHUNKY_XBGR_MAP 0x50000000 +#define MDI_CHUNKY_BGR_MAP 0x60000000 + +/* 16 bits */ +#define MDI_PLANAR_X16_MAP 0x70000000 +#define MDI_PLANAR_C16_MAP 0x80000000 + +/* 8 bit is done as CG3 MMAP offset */ +/* 32 bits, planar */ +#define MDI_PLANAR_X32_MAP 0x90000000 +#define MDI_PLANAR_B32_MAP 0xa0000000 +#define MDI_PLANAR_G32_MAP 0xb0000000 +#define MDI_PLANAR_R32_MAP 0xc0000000 + +/* Mappable offsets on leo */ +#define LEO_SS0_MAP 0x00000000 +#define LEO_LC_SS0_USR_MAP 0x00800000 +#define LEO_LD_SS0_MAP 0x00801000 +#define LEO_LX_CURSOR_MAP 0x00802000 +#define LEO_SS1_MAP 0x00803000 +#define LEO_LC_SS1_USR_MAP 0x01003000 +#define LEO_LD_SS1_MAP 0x01004000 +#define LEO_UNK_MAP 0x01005000 +#define LEO_LX_KRN_MAP 0x01006000 +#define LEO_LC_SS0_KRN_MAP 0x01007000 +#define LEO_LC_SS1_KRN_MAP 0x01008000 +#define LEO_LD_GBL_MAP 0x01009000 +#define LEO_UNK2_MAP 0x0100a000 + +#endif /* __LINUX_FBIO_H */ diff --git a/include/asm-sparc/fcntl.h b/include/asm-sparc/fcntl.h new file mode 100644 index 000000000..792e29b56 --- /dev/null +++ b/include/asm-sparc/fcntl.h @@ -0,0 +1,60 @@ +/* $Id: fcntl.h,v 1.8 1996/10/27 08:55:26 davem Exp $ */ +#ifndef _SPARC_FCNTL_H +#define _SPARC_FCNTL_H + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_ACCMODE 0x0003 +#define O_NDELAY 0x0004 +#define O_APPEND 0x0008 +#define FASYNC 0x0040 /* fcntl, for BSD compatibility */ +#define O_CREAT 0x0200 /* not fcntl */ +#define O_TRUNC 0x0400 /* not fcntl */ +#define O_EXCL 0x0800 /* not fcntl */ +#define O_SYNC 0x2000 +#define O_NONBLOCK 0x4000 +#define O_NOCTTY 0x8000 /* not fcntl */ + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get f_flags */ +#define F_SETFD 2 /* set f_flags */ +#define F_GETFL 3 /* more flags (cloexec) */ +#define F_SETFL 4 +#define F_GETOWN 5 /* for sockets. */ +#define F_SETOWN 6 /* for sockets. */ +#define F_GETLK 7 +#define F_SETLK 8 +#define F_SETLKW 9 + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 1 +#define F_WRLCK 2 +#define F_UNLCK 3 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* operations for bsd flock(), also used by the kernel implementation */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +#define LOCK_UN 8 /* remove lock */ + +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; + short __unused; +}; + +#endif diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h new file mode 100644 index 000000000..3ccc79766 --- /dev/null +++ b/include/asm-sparc/floppy.h @@ -0,0 +1,359 @@ +/* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __ASM_SPARC_FLOPPY_H +#define __ASM_SPARC_FLOPPY_H + +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/idprom.h> +#include <asm/machines.h> +#include <asm/oplib.h> +#include <asm/auxio.h> +#include <asm/irq.h> + +/* References: + * 1) Netbsd Sun floppy driver. + * 2) NCR 82077 controller manual + * 3) Intel 82077 controller manual + */ +struct sun_flpy_controller { + volatile unsigned char status_82072; /* Main Status reg. */ +#define dcr_82072 status_82072 /* Digital Control reg. */ +#define status1_82077 status_82072 /* Auxiliary Status reg. 1 */ + + volatile unsigned char data_82072; /* Data fifo. */ +#define status2_82077 data_82072 /* Auxiliary Status reg. 2 */ + + volatile unsigned char dor_82077; /* Digital Output reg. */ + volatile unsigned char tapectl_82077; /* What the? Tape control reg? */ + + volatile unsigned char status_82077; /* Main Status Register. */ +#define drs_82077 status_82077 /* Digital Rate Select reg. */ + + volatile unsigned char data_82077; /* Data fifo. */ + volatile unsigned char ___unused; + volatile unsigned char dir_82077; /* Digital Input reg. */ +#define dcr_82077 dir_82077 /* Config Control reg. */ +}; + +/* You'll only ever find one controller on a SparcStation anyways. */ +static struct sun_flpy_controller *sun_fdc = NULL; +volatile unsigned char *fdc_status; + +struct sun_floppy_ops { + unsigned char (*fd_inb)(int port); + void (*fd_outb)(unsigned char value, int port); +}; + +static struct sun_floppy_ops sun_fdops; + +#define fd_inb(port) sun_fdops.fd_inb(port) +#define fd_outb(value,port) sun_fdops.fd_outb(value,port) +#define fd_enable_dma() sun_fd_enable_dma() +#define fd_disable_dma() sun_fd_disable_dma() +#define fd_request_dma() (0) /* nothing... */ +#define fd_free_dma() /* nothing... */ +#define fd_clear_dma_ff() /* nothing... */ +#define fd_set_dma_mode(mode) sun_fd_set_dma_mode(mode) +#define fd_set_dma_addr(addr) sun_fd_set_dma_addr(addr) +#define fd_set_dma_count(count) sun_fd_set_dma_count(count) +#define fd_enable_irq() /* nothing... */ +#define fd_disable_irq() /* nothing... */ +#define fd_cacheflush(addr, size) /* nothing... */ +#define fd_request_irq() sun_fd_request_irq() +#define fd_free_irq() /* nothing... */ +#if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */ +#define fd_dma_mem_alloc(size) ((unsigned long) vmalloc(size)) +#define fd_dma_mem_free(addr,size) (vfree((void *)(addr))) +#endif + +#define FLOPPY_MOTOR_MASK 0x10 + +/* It's all the same... */ +#define virt_to_bus(x) (x) +#define bus_to_virt(x) (x) + +/* XXX This isn't really correct. XXX */ +#define get_dma_residue(x) (0) + +#define FLOPPY0_TYPE 4 +#define FLOPPY1_TYPE 0 + +/* Super paranoid... */ +#undef HAVE_DISABLE_HLT + +/* Here is where we catch the floppy driver trying to initialize, + * therefore this is where we call the PROM device tree probing + * routine etc. on the Sparc. + */ +#define FDC1 sun_floppy_init() + +static int FDC2=-1; + +#define N_FDC 1 +#define N_DRIVE 8 + +/* No 64k boundary crossing problems on the Sparc. */ +#define CROSS_64KB(a,s) (0) + +/* Routines unique to each controller type on a Sun. */ +static unsigned char sun_82072_fd_inb(int port) +{ + switch(port & 7) { + default: + printk("floppy: Asked to read unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 4: /* FD_STATUS */ + return sun_fdc->status_82072 & ~STATUS_DMA; + case 5: /* FD_DATA */ + return sun_fdc->data_82072; + case 7: /* FD_DIR */ + return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0; + }; + panic("sun_82072_fd_inb: How did I get here?"); +} + +static void sun_82072_fd_outb(unsigned char value, int port) +{ + switch(port & 7) { + default: + printk("floppy: Asked to write to unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 2: /* FD_DOR */ + /* Oh geese, 82072 on the Sun has no DOR register, + * the functionality is implemented via the AUXIO + * I/O register. So we must emulate the behavior. + * + * ASSUMPTIONS: There will only ever be one floppy + * drive attached to a Sun controller + * and it will be at drive zero. + */ + { + unsigned bits = 0; + if (value & 0x10) bits |= AUXIO_FLPY_DSEL; + if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT; + set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT)); + } + break; + case 5: /* FD_DATA */ + sun_fdc->data_82072 = value; + break; + case 7: /* FD_DCR */ + sun_fdc->dcr_82072 = value; + break; + case 4: /* FD_STATUS */ + sun_fdc->status_82072 = value; + break; + }; + return; +} + +static unsigned char sun_82077_fd_inb(int port) +{ + switch(port & 7) { + default: + printk("floppy: Asked to read unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 4: /* FD_STATUS */ + return sun_fdc->status_82077 & ~STATUS_DMA; + case 5: /* FD_DATA */ + return sun_fdc->data_82077; + case 7: /* FD_DIR */ + /* XXX: Is DCL on 0x80 in sun4m? */ + return sun_fdc->dir_82077; + }; + panic("sun_82072_fd_inb: How did I get here?"); +} + +static void sun_82077_fd_outb(unsigned char value, int port) +{ + switch(port & 7) { + default: + printk("floppy: Asked to write to unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 2: /* FD_DOR */ + /* Happily, the 82077 has a real DOR register. */ + sun_fdc->dor_82077 = value; + break; + case 5: /* FD_DATA */ + sun_fdc->data_82077 = value; + break; + case 7: /* FD_DCR */ + sun_fdc->dcr_82077 = value; + break; + case 4: /* FD_STATUS */ + sun_fdc->status_82077 = value; + break; + }; + return; +} + +/* For pseudo-dma (Sun floppy drives have no real DMA available to + * them so we must eat the data fifo bytes directly ourselves) we have + * three state variables. doing_pdma tells our inline low-level + * assembly floppy interrupt entry point whether it should sit and eat + * bytes from the fifo or just transfer control up to the higher level + * floppy interrupt c-code. I tried very hard but I could not get the + * pseudo-dma to work in c-code without getting many overruns and + * underruns. If non-zero, doing_pdma encodes the direction of + * the transfer for debugging. 1=read 2=write + */ +char *pdma_vaddr; +unsigned long pdma_size; +volatile int doing_pdma = 0; + +/* This is software state */ +char *pdma_base = 0; +unsigned long pdma_areasize; + +/* Common routines to all controller types on the Sparc. */ +static __inline__ void virtual_dma_init(void) +{ + /* nothing... */ +} + +static __inline__ void sun_fd_disable_dma(void) +{ + doing_pdma = 0; + if (pdma_base) { + mmu_unlockarea(pdma_base, pdma_areasize); + pdma_base = 0; + } +} + +static __inline__ void sun_fd_set_dma_mode(int mode) +{ + switch(mode) { + case DMA_MODE_READ: + doing_pdma = 1; + break; + case DMA_MODE_WRITE: + doing_pdma = 2; + break; + default: + printk("Unknown dma mode %d\n", mode); + panic("floppy: Giving up..."); + } +} + +static __inline__ void sun_fd_set_dma_addr(char *buffer) +{ + pdma_vaddr = buffer; +} + +static __inline__ void sun_fd_set_dma_count(int length) +{ + pdma_size = length; +} + +static __inline__ void sun_fd_enable_dma(void) +{ + pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size); + pdma_base = pdma_vaddr; + pdma_areasize = pdma_size; +} + +/* Our low-level entry point in arch/sparc/kernel/entry.S */ +extern void floppy_hardint(int irq, void *unused, struct pt_regs *regs); + +static int sun_fd_request_irq(void) +{ + static int once = 0; + int error; + + if(!once) { + once = 1; + error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy"); + return ((error == 0) ? 0 : -1); + } else return 0; +} + +static struct linux_prom_registers fd_regs[2]; + +static int sun_floppy_init(void) +{ + char state[128]; + int tnode, fd_node, num_regs; + + use_virtual_dma = 1; + + FLOPPY_IRQ = 11; + /* Forget it if we aren't on a machine that could possibly + * ever have a floppy drive. + */ + if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) || + ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) { + /* We certainly don't have a floppy controller. */ + goto no_sun_fdc; + } + /* Well, try to find one. */ + tnode = prom_getchild(prom_root_node); + fd_node = prom_searchsiblings(tnode, "obio"); + if(fd_node != 0) { + tnode = prom_getchild(fd_node); + fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo"); + } else { + fd_node = prom_searchsiblings(tnode, "fd"); + } + if(fd_node == 0) { + goto no_sun_fdc; + } + + /* The sun4m lets us know if the controller is actually usable. */ + if(sparc_cpu_model == sun4m) { + prom_getproperty(fd_node, "status", state, sizeof(state)); + if(!strcmp(state, "disabled")) { + goto no_sun_fdc; + } + } + num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs)); + num_regs = (num_regs / sizeof(fd_regs[0])); + prom_apply_obio_ranges(fd_regs, num_regs); + sun_fdc = (struct sun_flpy_controller *) sparc_alloc_io(fd_regs[0].phys_addr, + 0x0, + fd_regs[0].reg_size, + "floppy", + fd_regs[0].which_io, + 0x0); + /* Last minute sanity check... */ + if(sun_fdc->status_82072 == 0xff) { + sun_fdc = NULL; + goto no_sun_fdc; + } + + if(sparc_cpu_model == sun4c) { + sun_fdops.fd_inb = sun_82072_fd_inb; + sun_fdops.fd_outb = sun_82072_fd_outb; + fdc_status = &sun_fdc->status_82072; + /* printk("AUXIO @0x%p\n", auxio_register); */ /* P3 */ + } else { + sun_fdops.fd_inb = sun_82077_fd_inb; + sun_fdops.fd_outb = sun_82077_fd_outb; + fdc_status = &sun_fdc->status_82077; + /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */ + } + + /* Success... */ + return (int) sun_fdc; + +no_sun_fdc: + return -1; +} + +static int sparc_eject(void) +{ + set_dor(0x00, 0xff, 0x90); + udelay(500); + set_dor(0x00, 0x6f, 0x00); + udelay(500); + return 0; +} + +#define fd_eject(drive) sparc_eject() + +#endif /* !(__ASM_SPARC_FLOPPY_H) */ diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h index b26067623..f89e41fc8 100644 --- a/include/asm-sparc/head.h +++ b/include/asm-sparc/head.h @@ -1,75 +1,114 @@ +/* $Id: head.h,v 1.30 1996/07/29 21:00:28 miguel Exp $ */ #ifndef __SPARC_HEAD_H #define __SPARC_HEAD_H -#define KERNSIZE 134217728 /* this is how much of a mapping the prom promises */ -#define PAGESIZE 4096 /* luckily this is the same on sun4c's and sun4m's */ -#define PAGESHIFT 12 -#define PROM_BASE -1568768 /* casa 'de PROM */ -#define LOAD_ADDR 0x4000 /* prom jumps to us here */ -#define C_STACK 96 +#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */ +#define LOAD_ADDR 0x4000 /* prom jumps to us here unless this is elf /boot */ #define SUN4C_SEGSZ (1 << 18) -#define USRSTACK 0x0 /* no joke, this is temporary, trust me */ -#define INT_ENABLE_REG_PHYSADR 0xf5000000 -#define INTS_ENAB 0x01 +#define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2) /* Used in boot remapping. */ +#define INTS_ENAB 0x01 /* entry.S uses this. */ -#define BOOT_MSG_LEN 61 -#define BOOT_MSG2_LEN 50 +#define NCPUS 4 /* Architectural limit of sun4m. */ +#define SUN4_PROM_VECTOR 0xFFE81000 /* To safely die on a SUN4 */ +#define SUN4_PRINTF 0x84 /* Offset into SUN4_PROM_VECTOR */ -#define WRITE_PAUSE nop; nop; nop; - -#define PAGE_SIZE 4096 +#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ +#define NOP_INSN 0x01000000 /* Used to patch sparc_save_state */ /* Here are some trap goodies */ - /* Generic trap entry. */ - #define TRAP_ENTRY(type, label) \ - mov (type), %l3; b label; rd %psr, %l0; nop; + rd %psr, %l0; b label; rd %wim, %l3; nop; + +/* Data/text faults. Defaults to sun4c version at boot time. */ +#define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7; +#define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7; +#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 1, %l7; +#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 0, %l7; + +/* This is for traps we should NEVER get. */ +#define BAD_TRAP(num) \ + rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3; + +/* Notice that for the system calls we pull a trick. We load up a + * different pointer to the system call vector table in %l7, but call + * the same generic system call low-level entry point. The trap table + * entry sequences are also HyperSparc pipeline friendly ;-) + */ + +/* Software trap for Linux system calls. */ +#define LINUX_SYSCALL_TRAP \ + sethi %hi(C_LABEL(sys_call_table)), %l7; \ + or %l7, %lo(C_LABEL(sys_call_table)), %l7; \ + b linux_sparc_syscall; \ + rd %psr, %l0; + +/* Software trap for SunOS4.1.x system calls. */ +#define SUNOS_SYSCALL_TRAP \ + rd %psr, %l0; \ + sethi %hi(C_LABEL(sunos_sys_table)), %l7; \ + b linux_sparc_syscall; \ + or %l7, %lo(C_LABEL(sunos_sys_table)), %l7; + +/* Software trap for Slowaris system calls. */ +#define SOLARIS_SYSCALL_TRAP \ + sethi %hi(C_LABEL(sys_call_table)), %l7; \ + or %l7, %lo(C_LABEL(sys_call_table)), %l7; \ + b solaris_syscall; \ + rd %psr, %l0; + +#define INDIRECT_SOLARIS_SYSCALL(x) \ + sethi %hi(C_LABEL(sys_call_table)), %l7; \ + or %g0,%lo(x),%g1; \ + b solaris_indirect_syscall; \ + rd %psr, %l0; + +#define BREAKPOINT_TRAP \ + b breakpoint_trap; \ + rd %psr,%l0; \ + nop; \ + nop; + +/* Software trap for Sparc-netbsd system calls. */ +#define NETBSD_SYSCALL_TRAP \ + sethi %hi(C_LABEL(sys_call_table)), %l7; \ + or %l7, %lo(C_LABEL(sys_call_table)), %l7; \ + b bsd_syscall; \ + rd %psr, %l0; + +/* The Get Condition Codes software trap for userland. */ +#define GETCC_TRAP \ + b getcc_trap_handler; mov %psr, %l0; nop; nop; + +/* The Set Condition Codes software trap for userland. */ +#define SETCC_TRAP \ + b setcc_trap_handler; mov %psr, %l0; nop; nop; /* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and * gets handled with another macro. */ - #define TRAP_ENTRY_INTERRUPT(int_level) \ - mov int_level, %l3; b stray_irq_entry; rd %psr, %l0; nop; - -/* Here is the macro for soft interrupts (ie. not as urgent as hard ones) - * which need to jump to a different handler. + mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3; + +/* NMI's (Non Maskable Interrupts) are special, you can't keep them + * from coming in, and basically if you get one, the shows over. ;( + * On the sun4c they are usually asynchronous memory errors, on the + * the sun4m they could be either due to mem errors or a software + * initiated interrupt from the prom/kern on an SMP box saying "I + * command you to do CPU tricks, read your mailbox for more info." */ +#define NMI_TRAP \ + rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop; -#define TRAP_ENTRY_INTERRUPT_SOFT(int_level, ident) \ - mov int_level, %l3; rd %psr, %l0; b stray_irq_entry; mov ident, %l4; - -/* The above two macros are for generic traps. The following is made - * especially for timer interrupts at IRQ level 14. - */ - -#define TRAP_ENTRY_TIMER \ - mov 10, %l3; rd %psr, %l0; b sparc_timer; nop; - -/* Non-maskable interrupt entry macro. You have to turn off all interrupts - * to not receive this. This is usually due to a asynchronous memory error. - * All we can really do is stop the show. :-( - */ - -#define TRAP_ENTRY_INTERRUPT_NMI(t_type, jmp_to) \ - mov t_type, %l3; b jmp_to; rd %psr, %l0; nop; - -/* Trap entry code in entry.S needs the offsets into task_struct - * to get at the thread_struct goodies during window craziness. - * - * NOTE: We need to keep these values under 0x3ff in order to do - * efficient load/stores in the window fill/spill handlers. - * See TRAP_WIN_CLEAN in entry.S for details. +/* Window overflows/underflows are special and we need to try to be as + * efficient as possible here.... */ +#define WINDOW_SPILL \ + rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0; -#define THREAD_UWINDOWS 0x3bc -#define THREAD_WIM 0x3c0 -#define THREAD_W_SAVED 0x3c4 -#define THREAD_KSP 0x3c8 -#define THREAD_USP 0x3cc -#define THREAD_REG_WINDOW 0x3d4 +#define WINDOW_FILL \ + rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0; #endif __SPARC_HEAD_H diff --git a/include/asm-sparc/idprom.h b/include/asm-sparc/idprom.h index e7a136891..d856e640a 100644 --- a/include/asm-sparc/idprom.h +++ b/include/asm-sparc/idprom.h @@ -1,21 +1,33 @@ -/* idprom.h: Macros and defines for idprom routines +/* $Id: idprom.h,v 1.6 1996/08/04 10:35:07 ecd Exp $ + * idprom.h: Macros and defines for idprom routines * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -extern struct linux_romvec *romvec; +#ifndef _SPARC_IDPROM_H +#define _SPARC_IDPROM_H -#define IDPROM_ADDR (0xffd04000 + 0x7d8) -#define IDPROM_SIZE 36 +/* Offset into the EEPROM where the id PROM is located on the 4c */ +#define IDPROM_OFFSET 0x7d8 -struct idp_struct +/* On sun4m; physical. */ +/* MicroSPARC(-II) does not decode 31rd bit, but it works. */ +#define IDPROM_OFFSET_M 0xfd8 + +struct idprom { - unsigned char id_f_id; /* format identifier */ - unsigned char id_machtype; /* Machine type */ - unsigned char id_eaddr[6]; /* hardware ethernet address */ - long id_domf; /* Date when this machine was manufactured */ - unsigned int id_sernum:24; /* Unique serial number */ - unsigned char id_cksum; /* XXX */ - unsigned char dummy[16]; /* XXX */ + unsigned char id_format; /* Format identifier (always 0x01) */ + unsigned char id_machtype; /* Machine type */ + unsigned char id_ethaddr[6]; /* Hardware ethernet address */ + long id_date; /* Date of manufacture */ + unsigned int id_sernum:24; /* Unique serial number */ + unsigned char id_cksum; /* Checksum - xor of the data bytes */ + unsigned char reserved[16]; }; +extern struct idprom *idprom; +extern void idprom_init(void); + +#define IDPROM_SIZE (sizeof(struct idprom)) + +#endif /* !(_SPARC_IDPROM_H) */ diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h index 5aa1a3fac..88adf1621 100644 --- a/include/asm-sparc/io.h +++ b/include/asm-sparc/io.h @@ -1,7 +1,11 @@ +/* $Id: io.h,v 1.10 1996/08/29 09:48:14 davem Exp $ */ #ifndef __SPARC_IO_H #define __SPARC_IO_H +#include <linux/kernel.h> + #include <asm/page.h> /* IO address mapping routines need this */ +#include <asm/system.h> /* * Defines for io operations on the Sparc. Whether a memory access is going @@ -10,91 +14,129 @@ * space only works on sun4's */ -extern inline unsigned long inb_local(unsigned long addr) +extern __inline__ unsigned long inb_local(unsigned long addr) { - return 0; + return 0; } -extern inline void outb_local(unsigned char b, unsigned long addr) +extern __inline__ void outb_local(unsigned char b, unsigned long addr) { - return; + return; } -extern inline unsigned long inb(unsigned long addr) +extern __inline__ unsigned long inb(unsigned long addr) { - return 0; + return 0; } -extern inline unsigned long inw(unsigned long addr) +extern __inline__ unsigned long inw(unsigned long addr) { - return 0; + return 0; } -extern inline unsigned long inl(unsigned long addr) +extern __inline__ unsigned long inl(unsigned long addr) { - return 0; + return 0; } -extern inline void outb(unsigned char b, unsigned long addr) +extern __inline__ void outb(unsigned char b, unsigned long addr) { - return; + return; } -extern inline void outw(unsigned short b, unsigned long addr) +extern __inline__ void outw(unsigned short b, unsigned long addr) { - return; + return; } -extern inline void outl(unsigned int b, unsigned long addr) +extern __inline__ void outl(unsigned int b, unsigned long addr) { - return; + return; } /* * Memory functions */ -extern inline unsigned long readb(unsigned long addr) +extern __inline__ unsigned long readb(unsigned long addr) { - return 0; + return 0; } -extern inline unsigned long readw(unsigned long addr) +extern __inline__ unsigned long readw(unsigned long addr) { - return 0; + return 0; } -extern inline unsigned long readl(unsigned long addr) +extern __inline__ unsigned long readl(unsigned long addr) { - return 0; + return 0; } -extern inline void writeb(unsigned short b, unsigned long addr) +extern __inline__ void writeb(unsigned short b, unsigned long addr) { - return; + return; } -extern inline void writew(unsigned short b, unsigned long addr) +extern __inline__ void writew(unsigned short b, unsigned long addr) { - return; + return; } -extern inline void writel(unsigned int b, unsigned long addr) +extern __inline__ void writel(unsigned int b, unsigned long addr) { - return; + return; } #define inb_p inb #define outb_p outb -extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr) +extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly); +extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly); + +extern __inline__ void mapioaddr(unsigned long physaddr, unsigned long virt_addr, + int bus, int rdonly) { - unsigned long page_entry; + switch(sparc_cpu_model) { + case sun4c: + sun4c_mapioaddr(physaddr, virt_addr, bus, rdonly); + break; + case sun4m: + case sun4d: + case sun4e: + srmmu_mapioaddr(physaddr, virt_addr, bus, rdonly); + break; + default: + printk("mapioaddr: Trying to map IO space for unsupported machine.\n"); + printk("mapioaddr: sparc_cpu_model = %d\n", sparc_cpu_model); + printk("mapioaddr: Halting...\n"); + halt(); + }; + return; +} - page_entry = physaddr >> PAGE_SHIFT; - page_entry |= (PTE_V | PTE_ACC | PTE_NC | PTE_IO); /* kernel io addr */ +extern void srmmu_unmapioaddr(unsigned long virt); +extern void sun4c_unmapioaddr(unsigned long virt); - put_pte(virt_addr, page_entry); - return; +extern __inline__ void unmapioaddr(unsigned long virt_addr) +{ + switch(sparc_cpu_model) { + case sun4c: + sun4c_unmapioaddr(virt_addr); + break; + case sun4m: + case sun4d: + case sun4e: + srmmu_unmapioaddr(virt_addr); + break; + default: + printk("unmapioaddr: sparc_cpu_model = %d, halt...\n", sparc_cpu_model); + halt(); + }; + return; } +extern void *sparc_alloc_io (void *, void *, int, char *, int, int); +extern void sparc_free_io (void *, int); +extern void *sparc_dvma_malloc (int, char *); + #endif /* !(__SPARC_IO_H) */ diff --git a/include/asm-sparc/ioctl.h b/include/asm-sparc/ioctl.h new file mode 100644 index 000000000..e6c645fff --- /dev/null +++ b/include/asm-sparc/ioctl.h @@ -0,0 +1,43 @@ +/* $Id: ioctl.h,v 1.5 1996/05/17 03:31:09 davem Exp $ */ +#ifndef _SPARC_IOCTL_H +#define _SPARC_IOCTL_H + +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 8 +#define _IOC_RESVBITS 5 +#define _IOC_DIRBITS 3 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_RESVMASK ((1 << _IOC_RESVBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT + _IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT + _IOC_TYPEBITS) +#define _IOC_RESVSHIFT (_IOC_SIZESHIFT + _IOC_SIZEBITS) +#define _IOC_DIRSHIFT (_IOC_RESVSHIFT + _IOC_RESVBITS) + +#define _IOC_NONE 1U +#define _IOC_READ 2U +#define _IOC_WRITE 4U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +#endif /* !(_SPARC_IOCTL_H) */ diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h new file mode 100644 index 000000000..80eff02ea --- /dev/null +++ b/include/asm-sparc/ioctls.h @@ -0,0 +1,128 @@ +#ifndef _ASM_SPARC_IOCTLS_H +#define _ASM_SPARC_IOCTLS_H + +#include <asm/ioctl.h> + +/* Big T */ +#define TCGETA _IOR('T', 1, struct termio) +#define TCSETA _IOW('T', 2, struct termio) +#define TCSETAW _IOW('T', 3, struct termio) +#define TCSETAF _IOW('T', 4, struct termio) +#define TCSBRK _IO('T', 5) +#define TCXONC _IO('T', 6) +#define TCFLSH _IO('T', 7) +#define TCGETS _IOR('T', 8, struct termios) +#define TCSETS _IOW('T', 9, struct termios) +#define TCSETSW _IOW('T', 10, struct termios) +#define TCSETSF _IOW('T', 11, struct termios) + +/* Note that all the ioctls that are not available in Linux have a + * double underscore on the front to: a) avoid some programs to + * thing we support some ioctls under Linux (autoconfiguration stuff) + */ +/* Little t */ +#define TIOCGETD _IOR('t', 0, int) +#define TIOCSETD _IOW('t', 1, int) +#define __TIOCHPCL _IO('t', 2) /* SunOS Specific */ +#define __TIOCMODG _IOR('t', 3, int) /* SunOS Specific */ +#define __TIOCMODS _IOW('t', 4, int) /* SunOS Specific */ +#define __TIOCGETP _IOR('t', 8, struct sgttyb) /* SunOS Specific */ +#define __TIOCSETP _IOW('t', 9, struct sgttyb) /* SunOS Specific */ +#define __TIOCSETN _IOW('t', 10, struct sgttyb) /* SunOS Specific */ +#define TIOCEXCL _IO('t', 13) +#define TIOCNXCL _IO('t', 14) +#define __TIOCFLUSH _IOW('t', 16, int) /* SunOS Specific */ +#define __TIOCSETC _IOW('t', 17, struct tchars) /* SunOS Specific */ +#define __TIOCGETC _IOR('t', 18, struct tchars) /* SunOS Specific */ +#define __TIOCTCNTL _IOW('t', 32, int) /* SunOS Specific */ +#define __TIOCSIGNAL _IOW('t', 33, int) /* SunOS Specific */ +#define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */ +#define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */ +#define TIOCCONS _IO('t', 36) +#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ +#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ +#define TIOCGSOFTCAR _IOR('t', 100, int) +#define TIOCSSOFTCAR _IOW('t', 101, int) +#define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */ +#define TIOCSWINSZ _IOW('t', 103, struct winsize) +#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define __TIOCREMOTE _IOW('t', 105, int) /* SunOS Specific */ +#define TIOCMGET _IOR('t', 106, int) +#define TIOCMBIC _IOW('t', 107, int) +#define TIOCMBIS _IOW('t', 108, int) +#define TIOCMSET _IOW('t', 109, int) +#define __TIOCSTART _IO('t', 110) /* SunOS Specific */ +#define __TIOCSTOP _IO('t', 111) /* SunOS Specific */ +#define TIOCPKT _IOW('t', 112, int) +#define TIOCNOTTY _IO('t', 113) +#define TIOCSTI _IOW('t', 114, char) +#define TIOCOUTQ _IOR('t', 115, int) +#define __TIOCGLTC _IOR('t', 116, struct ltchars) /* SunOS Specific */ +#define __TIOCSLTC _IOW('t', 117, struct ltchars) /* SunOS Specific */ +/* 118 is the non-posix setpgrp tty ioctl */ +/* 119 is the non-posix getpgrp tty ioctl */ +#define __TIOCCDTR _IO('t', 120) /* SunOS Specific */ +#define __TIOCSDTR _IO('t', 121) /* SunOS Specific */ +#define __TIOCCBRK _IO('t', 122) /* SunOS Specific */ +#define __TIOCSBRK _IO('t', 123) /* SunOS Specific */ +#define __TIOCLGET _IOW('t', 124, int) /* SunOS Specific */ +#define __TIOCLSET _IOW('t', 125, int) /* SunOS Specific */ +#define __TIOCLBIC _IOW('t', 126, int) /* SunOS Specific */ +#define __TIOCLBIS _IOW('t', 127, int) /* SunOS Specific */ +#define __TIOCISPACE _IOR('t', 128, int) /* SunOS Specific */ +#define __TIOCISIZE _IOR('t', 129, int) /* SunOS Specific */ +#define TIOCSPGRP _IOW('t', 130, int) +#define TIOCGPGRP _IOR('t', 131, int) +#define TIOCSCTTY _IO('t', 132) + +/* Little f */ +#define FIOCLEX _IO('f', 1) +#define FIONCLEX _IO('f', 2) +#define FIOASYNC _IOW('f', 125, int) +#define FIONBIO _IOW('f', 126, int) +#define FIONREAD _IOR('f', 127, int) +#define TIOCINQ FIONREAD + +/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it + * someday. This is completely bogus, I know... + */ +#define __TCGETSTAT _IO('T', 200) /* Rutgers specific */ +#define __TCSETSTAT _IO('T', 201) /* Rutgers specific */ + +/* Linux specific, no SunOS equivalent. */ +#define TIOCLINUX 0x541C +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TCSBRKP 0x5425 +#define TIOCTTYGSTRUCT 0x5426 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +/* Kernel definitions */ +#ifdef __KERNEL__ +#define TIOCGETC __TIOCGETC +#define TIOCGETP __TIOCGETP +#define TIOCGLTC __TIOCGLTC +#define TIOCSLTC __TIOCSLTC +#define TIOCSETP __TIOCSETP +#define TIOCSETN __TIOCSETN +#define TIOCSETC __TIOCSETC +#endif + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#endif /* !(_ASM_SPARC_IOCTLS_H) */ diff --git a/include/asm-sparc/iommu.h b/include/asm-sparc/iommu.h new file mode 100644 index 000000000..cf1d5b794 --- /dev/null +++ b/include/asm-sparc/iommu.h @@ -0,0 +1,120 @@ +/* iommu.h: Definitions for the sun4m IOMMU. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_IOMMU_H +#define _SPARC_IOMMU_H + +#include <asm/page.h> + +/* The iommu handles all virtual to physical address translations + * that occur between the SBUS and physical memory. Access by + * the cpu to IO registers and similar go over the mbus so are + * translated by the on chip SRMMU. The iommu and the srmmu do + * not need to have the same translations at all, in fact most + * of the time the translations they handle are a disjunct set. + * Basically the iommu handles all dvma sbus activity. + */ + +/* The IOMMU registers occupy three pages in IO space. */ +struct iommu_regs { + /* First page */ + volatile unsigned long control; /* IOMMU control */ + volatile unsigned long base; /* Physical base of iopte page table */ + volatile unsigned long _unused1[3]; + volatile unsigned long tlbflush; /* write only */ + volatile unsigned long pageflush; /* write only */ + volatile unsigned long _unused2[1017]; + /* Second page */ + volatile unsigned long afsr; /* Async-fault status register */ + volatile unsigned long afar; /* Async-fault physical address */ + volatile unsigned long _unused3[2]; + volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */ + volatile unsigned long sbuscfg1; + volatile unsigned long sbuscfg2; + volatile unsigned long sbuscfg3; + volatile unsigned long mfsr; /* Memory-fault status register */ + volatile unsigned long mfar; /* Memory-fault physical address */ + volatile unsigned long _unused4[1014]; + /* Third page */ + volatile unsigned long mid; /* IOMMU module-id */ +}; + +#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */ +#define IOMMU_CTRL_VERS 0x0f000000 /* Version */ +#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */ +#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */ +#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */ +#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */ +#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */ +#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */ +#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */ +#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */ +#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */ +#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */ + +#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */ +#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */ +#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */ +#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */ +#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */ +#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */ +#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */ +#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */ +#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */ + +#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */ +#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */ +#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */ +#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses + produced by this device as pure + physical. */ + +#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */ +#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */ +#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */ +#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred + on the even word of the access, low bit + indicated odd word caused the parity error */ +#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */ +#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */ +#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */ + +#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */ +#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */ +#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */ +#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */ +#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */ +#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */ +#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */ + +/* The format of an iopte in the page tables */ +#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */ +#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */ +#define IOPTE_WRITE 0x00000004 /* Writeable */ +#define IOPTE_VALID 0x00000002 /* IOPTE is valid */ +#define IOPTE_WAZ 0x00000001 /* Write as zeros */ + +struct iommu_struct { + struct iommu_regs *regs; + iopte_t *page_table; + iopte_t *lowest; /* to speed up searches... */ + unsigned long plow; + /* For convenience */ + unsigned long start; /* First managed virtual address */ + unsigned long end; /* Last managed virtual address */ +}; + +extern __inline__ void iommu_invalidate(struct iommu_regs *regs) +{ + regs->tlbflush = 0; +} + +extern __inline__ void iommu_invalidate_page(struct iommu_regs *regs, unsigned long page) +{ + regs->pageflush = (page & PAGE_MASK); +} + +#endif /* !(_SPARC_IOMMU_H) */ diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index 0e96ffb8c..7b1a13efb 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -1,43 +1,126 @@ -#ifndef _ALPHA_IRQ_H -#define _ALPHA_IRQ_H - -/* - * linux/include/asm-sparc/irq.h +/* $Id: irq.h,v 1.14 1996/08/29 09:48:18 davem Exp $ + * irq.h: IRQ registers on the Sparc. * - * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#ifndef _SPARC_IRQ_H +#define _SPARC_IRQ_H + #include <linux/linkage.h> -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); +#include <asm/system.h> /* For NCPUS */ + +#define NR_IRQS 15 + +/* Dave Redman (djhr@tadpole.co.uk) + * changed these to function pointers.. it saves cycles and will allow + * the irq dependencies to be split into different files at a later date + * sun4c_irq.c, sun4m_irq.c etc so we could reduce the kernel size. + */ +extern void (*disable_irq)(unsigned int); +extern void (*enable_irq)(unsigned int); +extern void (*clear_clock_irq)( void ); +extern void (*clear_profile_irq)( void ); +extern void (*load_profile_irq)( unsigned int timeout ); +extern void (*init_timers)(void (*lvl10_irq)(int, void *, struct pt_regs *)); +extern void claim_ticker14(void (*irq_handler)(int, void *, struct pt_regs *), + int irq, + unsigned int timeout); + +#ifdef __SMP__ +extern void (*set_cpu_int)(int, int); +extern void (*clear_cpu_int)(int, int); +extern void (*set_irq_udt)(int); +#endif + +extern int request_fast_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, __const__ char *devname); + +/* On the sun4m, just like the timers, we have both per-cpu and master + * interrupt registers. + */ + +/* These registers are used for sending/receiving irqs from/to + * different cpu's. + */ +struct sun4m_intreg_percpu { + unsigned int tbt; /* Interrupts still pending for this cpu. */ -#define __STR(x) #x -#define STR(x) __STR(x) - -#define SAVE_ALL "xx" + /* These next two registers are WRITE-ONLY and are only + * "on bit" sensitive, "off bits" written have NO affect. + */ + unsigned int clear; /* Clear this cpus irqs here. */ + unsigned int set; /* Set this cpus irqs here. */ + unsigned char space[PAGE_SIZE - 12]; +}; -#define SAVE_MOST "yy" +/* + * djhr + * Actually the clear and set fields in this struct are misleading.. + * according to the SLAVIO manual (and the same applies for the SEC) + * the clear field clears bits in the mask which will ENABLE that IRQ + * the set field sets bits in the mask to DISABLE the IRQ. + * + * Also the undirected_xx address in the SLAVIO is defined as + * RESERVED and write only.. + * + * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor + * sun4m machines, for MP the layout makes more sense. + */ +struct sun4m_intregs { + struct sun4m_intreg_percpu cpu_intregs[NCPUS]; + unsigned int tbt; /* IRQ's that are still pending. */ + unsigned int irqs; /* Master IRQ bits. */ -#define RESTORE_MOST "zz" + /* Again, like the above, two these registers are WRITE-ONLY. */ + unsigned int clear; /* Clear master IRQ's by setting bits here. */ + unsigned int set; /* Set master IRQ's by setting bits here. */ -#define ACK_FIRST(mask) "aa" + /* This register is both READ and WRITE. */ + unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +}; -#define ACK_SECOND(mask) "dummy" +extern struct sun4m_intregs *sun4m_interrupts; + +/* + * Bit field defines for the interrupt registers on various + * Sparc machines. + */ + +/* The sun4c interrupt register. */ +#define SUN4C_INT_ENABLE 0x01 /* Allow interrupts. */ +#define SUN4C_INT_E14 0x80 /* Enable level 14 IRQ. */ +#define SUN4C_INT_E10 0x20 /* Enable level 10 IRQ. */ +#define SUN4C_INT_E8 0x10 /* Enable level 8 IRQ. */ +#define SUN4C_INT_E6 0x08 /* Enable level 6 IRQ. */ +#define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */ +#define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */ + +/* Dave Redman (djhr@tadpole.co.uk) + * The sun4m interrupt registers. + */ +#define SUN4M_INT_ENABLE 0x80000000 +#define SUN4M_INT_E14 0x00000080 +#define SUN4M_INT_E10 0x00080000 -#define UNBLK_FIRST(mask) "dummy" +#define SUN4M_HARD_INT(x) (0x000000001 << (x)) +#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) -#define UNBLK_SECOND(mask) "dummy" +#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ +#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ +#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ +#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ +#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ +#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ +#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ +#define SUN4M_INT_REALTIME 0x00080000 /* system timer */ +#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ +#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ +#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ +#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ +#define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ +#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ -#define IRQ_NAME2(nr) nr##_interrupt(void) -#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) -#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) -#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) - -#define BUILD_IRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ -asm code comes here +#define SUN4M_INT_SBUS(x) (1 << (x+7)) #endif diff --git a/include/asm-sparc/kbio.h b/include/asm-sparc/kbio.h new file mode 100644 index 000000000..7382d396f --- /dev/null +++ b/include/asm-sparc/kbio.h @@ -0,0 +1,44 @@ +#ifndef __LINUX_KBIO_H +#define __LINUX_KBIO_H + +/* Return keyboard type */ +#define KIOCTYPE _IOR('k', 9, int) +/* Return Keyboard layout */ +#define KIOCLAYOUT _IOR('k', 20, int) + +enum { + TR_NONE, + TR_ASCII, /* keyboard is in regular state */ + TR_EVENT, /* keystrokes sent as firm events */ + TR_UNTRANS_EVENT /* EVENT+up and down+no translation */ +}; + +/* Return the current keyboard translation */ +#define KIOCGTRANS _IOR('k', 5, int) +/* Set the keyboard translation */ +#define KIOCTRANS _IOW('k', 0, int) + +/* Send a keyboard command */ +#define KIOCCMD _IOW('k', 8, int) + +/* Return if keystrokes are being sent to /dev/kbd */ + +/* Set routing of keystrokes to /dev/kbd */ +#define KIOCSDIRECT _IOW('k', 10, int) + +/* Set keyboard leds */ +#define KIOCSLED _IOW('k', 14, unsigned char) + +/* Get keyboard leds */ +#define KIOCGLED _IOR('k', 15, unsigned char) + +/* Top bit records if the key is up or down */ +#define KBD_UP 0x80 + +/* Usable information */ +#define KBD_KEYMASK 0x7f + +/* All keys up */ +#define KBD_IDLE 0x75 + +#endif /* __LINUX_KBIO_H */ diff --git a/include/asm-sparc/kdebug.h b/include/asm-sparc/kdebug.h new file mode 100644 index 000000000..8607d9b5c --- /dev/null +++ b/include/asm-sparc/kdebug.h @@ -0,0 +1,79 @@ +/* $Id: kdebug.h,v 1.9 1996/05/10 19:52:35 davem Exp $ + * kdebug.h: Defines and definitions for debugging the Linux kernel + * under various kernel debuggers. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_KDEBUG_H +#define _SPARC_KDEBUG_H + +#include <asm/openprom.h> + +/* The debugger lives in 1MB of virtual address space right underneath + * the boot prom. + */ + +#define DEBUG_FIRSTVADDR 0xffc00000 +#define DEBUG_LASTVADDR LINUX_OPPROM_BEGVM + +/* Breakpoints are enter through trap table entry 126. So in sparc assembly + * if you want to drop into the debugger you do: + * + * t DEBUG_BP_TRAP + */ + +#define DEBUG_BP_TRAP 126 + +#ifndef __ASSEMBLY__ +/* The debug vector is passed in %o1 at boot time. It is a pointer to + * a structure in the debuggers address space. Here is its format. + */ + +typedef unsigned int (*debugger_funct)(void); + +struct kernel_debug { + /* First the entry point into the debugger. You jump here + * to give control over to the debugger. + */ + unsigned long kdebug_entry; + unsigned long kdebug_trapme; /* Figure out later... */ + /* The following is the number of pages that the debugger has + * taken from to total pool. + */ + unsigned long *kdebug_stolen_pages; + /* Ok, after you remap yourself and/or change the trap table + * from what you were left with at boot time you have to call + * this synchronization function so the debugger can check out + * what you have done. + */ + debugger_funct teach_debugger; +}; /* I think that is it... */ + +extern struct kernel_debug *linux_dbvec; + +/* Use this macro in C-code to enter the debugger. */ +extern __inline__ void sp_enter_debugger(void) +{ + __asm__ __volatile__("jmpl %0, %%o7\n\t" + "nop\n\t" : : + "r" (linux_dbvec) : "o7", "memory"); +} + +#define SP_ENTER_DEBUGGER do { \ + if((linux_dbvec!=0) && ((*(short *)linux_dbvec)!=-1)) \ + sp_enter_debugger(); \ + } while(0) + +#endif /* !(__ASSEMBLY__) */ + +/* Some nice offset defines for assembler code. */ +#define KDEBUG_ENTRY_OFF 0x0 +#define KDEBUG_DUNNO_OFF 0x4 +#define KDEBUG_DUNNO2_OFF 0x8 +#define KDEBUG_TEACH_OFF 0xc + +/* ugh... */ +#define TRAP_TRACE(reg1, reg2) \ + + +#endif /* !(_SPARC_KDEBUG_H) */ diff --git a/include/asm-sparc/kgdb.h b/include/asm-sparc/kgdb.h new file mode 100644 index 000000000..79534dac8 --- /dev/null +++ b/include/asm-sparc/kgdb.h @@ -0,0 +1,90 @@ +/* $Id: kgdb.h,v 1.7 1995/11/27 02:43:18 davem Exp $ + * kgdb.h: Defines and declarations for serial line source level + * remote debugging of the Linux kernel using gdb. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_KGDB_H +#define _SPARC_KGDB_H + +#ifndef __ASSEMBLY__ +/* To init the kgdb engine. */ +extern void set_debug_traps(void); + +/* To enter the debugger explicitly. */ +extern void breakpoint(void); + +/* For convenience we define the format of a kgdb trap breakpoint + * frame here also. + */ +struct kgdb_frame { + unsigned long globals[8]; + unsigned long outs[8]; + unsigned long locals[8]; + unsigned long ins[8]; + unsigned long fpregs[32]; + unsigned long y; + unsigned long psr; + unsigned long wim; + unsigned long tbr; + unsigned long pc; + unsigned long npc; + unsigned long fpsr; + unsigned long cpsr; +}; +#endif /* !(__ASSEMBLY__) */ + +/* Macros for assembly usage of the kgdb breakpoint frame. */ +#define KGDB_G0 0x000 +#define KGDB_G1 0x004 +#define KGDB_G2 0x008 +#define KGDB_G4 0x010 +#define KGDB_G6 0x018 +#define KGDB_I0 0x020 +#define KGDB_I2 0x028 +#define KGDB_I4 0x030 +#define KGDB_I6 0x038 +#define KGDB_Y 0x100 +#define KGDB_PSR 0x104 +#define KGDB_WIM 0x108 +#define KGDB_TBR 0x10c +#define KGDB_PC 0x110 +#define KGDB_NPC 0x114 + +#define SAVE_KGDB_GLOBALS(reg) \ + std %g0, [%reg + REGWIN_SZ + KGDB_G0]; \ + std %g2, [%reg + REGWIN_SZ + KGDB_G2]; \ + std %g4, [%reg + REGWIN_SZ + KGDB_G4]; \ + std %g6, [%reg + REGWIN_SZ + KGDB_G6]; + +#define SAVE_KGDB_INS(reg) \ + std %i0, [%reg + REGWIN_SZ + KGDB_I0]; \ + std %i2, [%reg + REGWIN_SZ + KGDB_I2]; \ + std %i4, [%reg + REGWIN_SZ + KGDB_I4]; \ + std %i6, [%reg + REGWIN_SZ + KGDB_I6]; + +#define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \ + st %reg_y, [%reg + REGWIN_SZ + KGDB_Y]; \ + st %reg_psr, [%reg + REGWIN_SZ + KGDB_PSR]; \ + st %reg_wim, [%reg + REGWIN_SZ + KGDB_WIM]; \ + st %reg_tbr, [%reg + REGWIN_SZ + KGDB_TBR]; \ + st %reg_pc, [%reg + REGWIN_SZ + KGDB_PC]; \ + st %reg_npc, [%reg + REGWIN_SZ + KGDB_NPC]; + +#define LOAD_KGDB_GLOBALS(reg) \ + ld [%reg + REGWIN_SZ + KGDB_G1], %g1; \ + ldd [%reg + REGWIN_SZ + KGDB_G2], %g2; \ + ldd [%reg + REGWIN_SZ + KGDB_G4], %g4; \ + ldd [%reg + REGWIN_SZ + KGDB_G6], %g6; + +#define LOAD_KGDB_INS(reg) \ + ldd [%reg + REGWIN_SZ + KGDB_I0], %i0; \ + ldd [%reg + REGWIN_SZ + KGDB_I2], %i2; \ + ldd [%reg + REGWIN_SZ + KGDB_I4], %i4; \ + ldd [%reg + REGWIN_SZ + KGDB_I6], %i6; + +#define LOAD_KGDB_SREGS(reg, reg_y_and_psr, reg_pc_and_npc) \ + ldd [%reg + REGWIN_SZ + KGDB_Y], %reg_y_and_psr; \ + ldd [%reg + REGWIN_SZ + KGDB_PC], %reg_pc_and_npc; + +#endif /* !(_SPARC_KGDB_H) */ diff --git a/include/asm-sparc/machines.h b/include/asm-sparc/machines.h new file mode 100644 index 000000000..d831350f5 --- /dev/null +++ b/include/asm-sparc/machines.h @@ -0,0 +1,69 @@ +/* $Id: machines.h,v 1.4 1995/11/25 02:31:58 davem Exp $ + * machines.h: Defines for taking apart the machine type value in the + * idprom and determining the kind of machine we are on. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_MACHINES_H +#define _SPARC_MACHINES_H + +struct Sun_Machine_Models { + char *name; + unsigned char id_machtype; +}; + +/* Current number of machines we know about that has an IDPROM + * machtype entry including one entry for the 0x80 OBP machines. + */ +#define NUM_SUN_MACHINES 15 + +extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES]; + +/* The machine type in the idprom area looks like this: + * + * --------------- + * | ARCH | MACH | + * --------------- + * 7 4 3 0 + * + * The ARCH field determines the architecture line (sun4, sun4c, etc). + * The MACH field determines the machine make within that architecture. + */ + +#define SM_ARCH_MASK 0xf0 +#define SM_SUN4 0x20 +#define SM_SUN4C 0x50 +#define SM_SUN4M 0x70 +#define SM_SUN4M_OBP 0x80 + +#define SM_TYP_MASK 0x0f +/* Sun4 machines */ +#define SM_4_260 0x01 /* Sun 4/200 series */ +#define SM_4_110 0x02 /* Sun 4/100 series */ +#define SM_4_330 0x03 /* Sun 4/300 series */ +#define SM_4_470 0x04 /* Sun 4/400 series */ + +/* Sun4c machines Full Name - PROM NAME */ +#define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */ +#define SM_4C_IPC 0x02 /* Sun4c SparcStation IPC - Sun 4/40 */ +#define SM_4C_SS1PLUS 0x03 /* Sun4c SparcStation 1+ - Sun 4/65 */ +#define SM_4C_SLC 0x04 /* Sun4c SparcStation SLC - Sun 4/20 */ +#define SM_4C_SS2 0x05 /* Sun4c SparcStation 2 - Sun 4/75 */ +#define SM_4C_ELC 0x06 /* Sun4c SparcStation ELC - Sun 4/25 */ +#define SM_4C_IPX 0x07 /* Sun4c SparcStation IPX - Sun 4/50 */ + +/* Sun4m machines, these predate the OpenBoot. These values only mean + * something if the value in the ARCH field is SM_SUN4M, if it is + * SM_SUN4M_OBP then you have the following situation: + * 1) You either have a sun4d, a sun4e, or a recently made sun4m. + * 2) You have to consult OpenBoot to determine which machine this is. + */ +#define SM_4M_SS60 0x01 /* Sun4m SparcSystem 600 */ +#define SM_4M_SS50 0x02 /* Sun4m SparcStation 10 */ +#define SM_4M_SS40 0x03 /* Sun4m SparcStation 5 */ + +/* Sun4d machines -- N/A */ +/* Sun4e machines -- N/A */ +/* Sun4u machines -- N/A */ + +#endif /* !(_SPARC_MACHINES_H) */ diff --git a/include/asm-sparc/mbus.h b/include/asm-sparc/mbus.h new file mode 100644 index 000000000..e5e5a18c8 --- /dev/null +++ b/include/asm-sparc/mbus.h @@ -0,0 +1,100 @@ +/* $Id: mbus.h,v 1.8 1996/08/29 09:48:21 davem Exp $ + * mbus.h: Various defines for MBUS modules. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_MBUS_H +#define _SPARC_MBUS_H + +#include <asm/ross.h> /* HyperSparc stuff */ +#include <asm/cypress.h> /* Cypress Chips */ +#include <asm/viking.h> /* Ugh, bug city... */ + +enum mbus_module { + HyperSparc = 0, + Cypress = 1, + Cypress_vE = 2, + Cypress_vD = 3, + Swift_ok = 4, + Swift_bad_c = 5, + Swift_lots_o_bugs = 6, + Tsunami = 7, + Viking_12 = 8, + Viking_2x = 9, + Viking_30 = 10, + Viking_35 = 11, + Viking_new = 12, + SRMMU_INVAL_MOD = 13, +}; + +extern enum mbus_module srmmu_modtype; +extern unsigned int viking_rev, swift_rev, cypress_rev; + +/* HW Mbus module bugs we have to deal with */ +#define HWBUG_COPYBACK_BROKEN 0x00000001 +#define HWBUG_ASIFLUSH_BROKEN 0x00000002 +#define HWBUG_VACFLUSH_BITROT 0x00000004 +#define HWBUG_KERN_ACCBROKEN 0x00000008 +#define HWBUG_KERN_CBITBROKEN 0x00000010 +#define HWBUG_MODIFIED_BITROT 0x00000020 +#define HWBUG_PC_BADFAULT_ADDR 0x00000040 +#define HWBUG_SUPERSCALAR_BAD 0x00000080 +#define HWBUG_PACINIT_BITROT 0x00000100 + +extern unsigned int hwbug_bitmask; + +/* First the module type values. To find out which you have, just load + * the mmu control register from ASI_M_MMUREG alternate address space and + * shift the value right 28 bits. + */ +/* IMPL field means the company which produced the chip. */ +#define MBUS_VIKING 0x4 /* bleech, Texas Instruments Module */ +#define MBUS_LSI 0x3 /* LSI Logics */ +#define MBUS_ROSS 0x1 /* Ross is nice */ +#define MBUS_FMI 0x0 /* Fujitsu Microelectronics/Swift */ + +/* Ross Module versions */ +#define ROSS_604_REV_CDE 0x0 /* revisions c, d, and e */ +#define ROSS_604_REV_F 0x1 /* revision f */ +#define ROSS_605 0xf /* revision a, a.1, and a.2 */ +#define ROSS_605_REV_B 0xe /* revision b */ + +/* TI Viking Module versions */ +#define VIKING_REV_12 0x1 /* Version 1.2 or SPARCclassic's CPU */ +#define VIKING_REV_2 0x2 /* Version 2.1, 2.2, 2.3, and 2.4 */ +#define VIKING_REV_30 0x3 /* Version 3.0 */ +#define VIKING_REV_35 0x4 /* Version 3.5 */ + +/* LSI Logics. */ +#define LSI_L64815 0x0 + +/* Fujitsu */ +#define FMI_AURORA 0x4 /* MB8690x, a Swift module... */ + +/* For multiprocessor support we need to be able to obtain the CPU id and + * the MBUS Module id. + */ + +/* The CPU ID is encoded in the trap base register, 20 bits to the left of + * bit zero, with 2 bits being significant. + */ +#define TBR_ID_SHIFT 20 + +extern __inline__ int get_cpuid(void) +{ + register int retval; + __asm__ __volatile__("rd %%tbr, %0\n\t" + "srl %0, %1, %0\n\t" : + "=r" (retval) : + "i" (TBR_ID_SHIFT)); + return (retval & 3); +} + +extern __inline__ int get_modid(void) +{ + return (get_cpuid() | 0x8); +} + + +#endif /* !(_SPARC_MBUS_H) */ diff --git a/include/asm-sparc/memerr.h b/include/asm-sparc/memerr.h deleted file mode 100644 index cd0ca3264..000000000 --- a/include/asm-sparc/memerr.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _SPARC_MEMERR_H -#define _SPARC_MEMERR_H - -/* memerr.h: Bit fields in the asynchronous and synchronous memory error - registers used to determine what 'type' of error has just - induced a trap. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ - -/* synchronous error register fields come first... */ - -#define SYNCER_WRITE 0x8000 /* write error... */ -#define SYNCER_INVAL 0x0080 /* invalid page access was attempted */ -#define SYNCER_PROT 0x0040 /* protection violation */ -#define SYNCER_TIMEOUT 0x0020 /* mem-bus access timeout (mem does not exist). */ -#define SYNCER_SBUSERR 0x0010 /* same as above, but for an SBUS access */ -#define SYNCER_MEMERR 0x0008 /* Bus parity error, lose lose... panic time */ -#define SYNCER_SZERR 0x0002 /* an attempted access was of BAD size, whoops */ -#define SYNCER_WATCHDOG 0x0001 /* although we never see these, the prom will.. */ - -/* asynchronous error bits go here */ - -#define ASYNCER_WBINVAL 0x80 /* situation arose where the cache tried to write - * back a page for which the valid bit was not set - * within the mmu. This is due to bad mm kernel bugs. - */ - -#define ASYNCER_TIMEOUT 0x20 /* mem-access bus timeout... */ -#define ASYNCER_DVMAERR 0x10 /* dvma transfer to/from memory bombed... */ - -#endif /* _SPARC_MEMERR_H */ diff --git a/include/asm-sparc/memreg.h b/include/asm-sparc/memreg.h new file mode 100644 index 000000000..c0498d3ba --- /dev/null +++ b/include/asm-sparc/memreg.h @@ -0,0 +1,52 @@ +/* $Id: memreg.h,v 1.8 1996/08/29 09:48:23 davem Exp $ */ +#ifndef _SPARC_MEMREG_H +#define _SPARC_MEMREG_H +/* memreg.h: Definitions of the values found in the synchronous + * and asynchronous memory error registers when a fault + * occurs on the sun4c. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +/* First the synchronous error codes, these are usually just + * normal page faults. + */ + +#define SUN4C_SYNC_WDRESET 0x0001 /* watchdog reset */ +#define SUN4C_SYNC_SIZE 0x0002 /* bad access size? whuz this? */ +#define SUN4C_SYNC_PARITY 0x0008 /* bad ram chips caused a parity error */ +#define SUN4C_SYNC_SBUS 0x0010 /* the SBUS had some problems... */ +#define SUN4C_SYNC_NOMEM 0x0020 /* translation to non-existent ram */ +#define SUN4C_SYNC_PROT 0x0040 /* access violated pte protections */ +#define SUN4C_SYNC_NPRESENT 0x0080 /* pte said that page was not present */ +#define SUN4C_SYNC_BADWRITE 0x8000 /* while writing something went bogus */ + +#define SUN4C_SYNC_BOLIXED \ + (SUN4C_SYNC_WDRESET | SUN4C_SYNC_SIZE | SUN4C_SYNC_SBUS | \ + SUN4C_SYNC_NOMEM | SUN4C_SYNC_PARITY) + +/* Now the asynchronous error codes, these are almost always produced + * by the cache writing things back to memory and getting a bad translation. + * Bad DVMA transactions can cause these faults too. + */ + +#define SUN4C_ASYNC_BADDVMA 0x0010 /* error during DVMA access */ +#define SUN4C_ASYNC_NOMEM 0x0020 /* write back pointed to bad phys addr */ +#define SUN4C_ASYNC_BADWB 0x0080 /* write back points to non-present page */ + +/* Memory parity error register with associated bit constants. */ +#ifndef __ASSEMBLY__ +extern __volatile__ unsigned long *sun4c_memerr_reg; +#endif + +#define SUN4C_MPE_ERROR 0x80 /* Parity error detected. (ro) */ +#define SUN4C_MPE_MULTI 0x40 /* Multiple parity errors detected. (ro) */ +#define SUN4C_MPE_TEST 0x20 /* Write inverse parity. (rw) */ +#define SUN4C_MPE_CHECK 0x10 /* Enable parity checking. (rw) */ +#define SUN4C_MPE_ERR00 0x08 /* Parity error in bits 0-7. (ro) */ +#define SUN4C_MPE_ERR08 0x04 /* Parity error in bits 8-15. (ro) */ +#define SUN4C_MPE_ERR16 0x02 /* Parity error in bits 16-23. (ro) */ +#define SUN4C_MPE_ERR24 0x01 /* Parity error in bits 24-31. (ro) */ +#define SUN4C_MPE_ERRS 0x0F /* Bit mask for the error bits. (ro) */ + +#endif /* !(_SPARC_MEMREG_H) */ diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h new file mode 100644 index 000000000..68bc526a1 --- /dev/null +++ b/include/asm-sparc/mman.h @@ -0,0 +1,49 @@ +/* $Id: mman.h,v 1.8 1996/10/27 08:55:28 davem Exp $ */ +#ifndef __SPARC_MMAN_H__ +#define __SPARC_MMAN_H__ + +/* SunOS'ified... */ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_NONE 0x0 /* page can not be accessed */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x0f /* Mask for type of mapping */ +#define MAP_FIXED 0x10 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x20 /* don't use a file */ +#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */ +#define MAP_NORESERVE 0x40 /* don't reserve swap pages */ +#define MAP_INHERIT 0x80 /* SunOS doesn't do this, but... */ +#define MAP_LOCKED 0x100 /* lock the mapping */ +#define _MAP_NEW 0x80000000 /* Binary compatibility is fun... */ + +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ + +#define MS_ASYNC 1 /* sync memory asynchronously */ +#define MS_INVALIDATE 2 /* invalidate the caches */ +#define MS_SYNC 4 /* synchronous memory sync */ + +#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */ +#define MCL_FUTURE 0x4000 /* lock all additions to address space */ + +/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system + * XXX calls. + */ + +/* SunOS sys_mctl() stuff... */ +#define MC_SYNC 1 /* Sync pages in memory with storage (usu. a file) */ +#define MC_LOCK 2 /* Lock pages into core ram, do not allow swapping of them */ +#define MC_UNLOCK 3 /* Unlock pages locked via previous mctl() with MC_LOCK arg */ +#define MC_LOCKAS 5 /* Lock an entire address space of the calling process */ +#define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 + +#endif /* __SPARC_MMAN_H__ */ diff --git a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h new file mode 100644 index 000000000..f9074dfae --- /dev/null +++ b/include/asm-sparc/mmu_context.h @@ -0,0 +1,14 @@ +#ifndef __SPARC_MMU_CONTEXT_H +#define __SPARC_MMU_CONTEXT_H + +/* For now I still leave the context handling in the + * switch_to() macro, I'll do it right soon enough. + */ +#define get_mmu_context(x) do { } while (0) + +/* Initialize the context related info for a new mm_struct + * instance. + */ +#define init_new_context(mm) ((mm)->context = NO_CONTEXT) + +#endif /* !(__SPARC_MMU_CONTEXT_H) */ diff --git a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h new file mode 100644 index 000000000..12baee12a --- /dev/null +++ b/include/asm-sparc/mostek.h @@ -0,0 +1,120 @@ +/* $Id: mostek.h,v 1.8 1996/11/04 00:45:30 ecd Exp $ + * mostek.h: Describes the various Mostek time of day clock registers. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) + */ + +#ifndef _SPARC_MOSTEK_H +#define _SPARC_MOSTEK_H + +#include <asm/idprom.h> + +/* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) + * + * Data + * Address Function + * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 + * 7ff - - - - - - - - Year 00-99 + * 7fe 0 0 0 - - - - - Month 01-12 + * 7fd 0 0 - - - - - - Date 01-31 + * 7fc 0 FT 0 0 0 - - - Day 01-07 + * 7fb KS 0 - - - - - - Hours 00-23 + * 7fa 0 - - - - - - - Minutes 00-59 + * 7f9 ST - - - - - - - Seconds 00-59 + * 7f8 W R S - - - - - Control + * + * * ST is STOP BIT + * * W is WRITE BIT + * * R is READ BIT + * * S is SIGN BIT + * * FT is FREQ TEST BIT + * * KS is KICK START BIT + */ + +/* The Mostek 48t02 real time clock and NVRAM chip. The registers + * other than the control register are in binary coded decimal. Some + * control bits also live outside the control register. + */ + +struct mostek48t02 { + volatile char eeprom[2008]; /* This is the eeprom, don't touch! */ + struct idprom idprom; /* The idprom lives here. */ + volatile unsigned char creg; /* Control register */ + volatile unsigned char sec; /* Seconds (0-59) */ + volatile unsigned char min; /* Minutes (0-59) */ + volatile unsigned char hour; /* Hour (0-23) */ + volatile unsigned char dow; /* Day of the week (1-7) */ + volatile unsigned char dom; /* Day of the month (1-31) */ + volatile unsigned char month; /* Month of year (1-12) */ + volatile unsigned char year; /* Year (0-99) */ +}; + +extern struct mostek48t02 *mstk48t02_regs; + +/* Control register values. */ +#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ +#define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ +#define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ + +/* Control bits that live in the other registers. */ +#define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ +#define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ +#define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ + +#define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ +#define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) + +/* Masks that define how much space each value takes up. */ +#define MSTK_SEC_MASK 0x7f +#define MSTK_MIN_MASK 0x7f +#define MSTK_HOUR_MASK 0x3f +#define MSTK_DOW_MASK 0x07 +#define MSTK_DOM_MASK 0x3f +#define MSTK_MONTH_MASK 0x1f +#define MSTK_YEAR_MASK 0xff + +/* Binary coded decimal conversion macros. */ +#define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) +#define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) + +/* Generic register set and get macros for internal use. */ +#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(regs->var & MSTK_ ## mask ## _MASK)) +#define MSTK_SET(regs,var,value,mask) do { regs->var &= ~(MSTK_ ## mask ## _MASK); regs->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0) + +/* Macros to make register access easier on our fingers. These give you + * the decimal value of the register requested if applicable. You pass + * the a pointer to a 'struct mostek48t02'. + */ +#define MSTK_REG_CREG(regs) (regs->creg) +#define MSTK_REG_SEC(regs) MSTK_GET(regs,sec,SEC) +#define MSTK_REG_MIN(regs) MSTK_GET(regs,min,MIN) +#define MSTK_REG_HOUR(regs) MSTK_GET(regs,hour,HOUR) +#define MSTK_REG_DOW(regs) MSTK_GET(regs,dow,DOW) +#define MSTK_REG_DOM(regs) MSTK_GET(regs,dom,DOM) +#define MSTK_REG_MONTH(regs) MSTK_GET(regs,month,MONTH) +#define MSTK_REG_YEAR(regs) MSTK_GET(regs,year,YEAR) + +#define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,sec,value,SEC) +#define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,min,value,MIN) +#define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,hour,value,HOUR) +#define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,dow,value,DOW) +#define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,dom,value,DOM) +#define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,month,value,MONTH) +#define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,year,value,YEAR) + + +/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the + * same (basically) layout of the 48t02 chip except for the extra + * NVRAM on board (8 KB against the 48t02's 2 KB). + */ +struct mostek48t08 { + char offset[6*1024]; /* Magic things may be here, who knows? */ + struct mostek48t02 regs; /* Here is what we are interested in. */ +}; +extern struct mostek48t08 *mstk48t08_regs; + +enum sparc_clock_type { MSTK48T02, MSTK48T08, MSTK_INVALID }; +extern enum sparc_clock_type sp_clock_typ; + +#endif /* !(_SPARC_MOSTEK_H) */ diff --git a/include/asm-sparc/mpmbox.h b/include/asm-sparc/mpmbox.h new file mode 100644 index 000000000..0e1bc5801 --- /dev/null +++ b/include/asm-sparc/mpmbox.h @@ -0,0 +1,67 @@ +/* $Id: mpmbox.h,v 1.4 1996/04/25 06:13:19 davem Exp $ + * mpmbox.h: Interface and defines for the OpenProm mailbox + * facilities for MP machines under Linux. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_MPMBOX_H +#define _SPARC_MPMBOX_H + +/* The prom allocates, for each CPU on the machine an unsigned + * byte in physical ram. You probe the device tree prom nodes + * for these values. The purpose of this byte is to be able to + * pass messages from one cpu to another. + */ + +/* These are the main message types we have to look for in our + * Cpu mailboxes, based upon these values we decide what course + * of action to take. + */ + +/* The CPU is executing code in the kernel. */ +#define MAILBOX_ISRUNNING 0xf0 + +/* Another CPU called romvec->pv_exit(), you should call + * prom_stopcpu() when you see this in your mailbox. + */ +#define MAILBOX_EXIT 0xfb + +/* Another CPU called romvec->pv_enter(), you should call + * prom_cpuidle() when this is seen. + */ +#define MAILBOX_GOSPIN 0xfc + +/* Another CPU has hit a breakpoint either into kadb or the prom + * itself. Just like MAILBOX_GOSPIN, you should call prom_cpuidle() + * at this point. + */ +#define MAILBOX_BPT_SPIN 0xfd + +/* Oh geese, some other nitwit got a damn watchdog reset. The party's + * over so go call prom_stopcpu(). + */ +#define MAILBOX_WDOG_STOP 0xfe + +#ifndef __ASSEMBLY__ + +/* Handy macro's to determine a cpu's state. */ + +/* Is the cpu still in Power On Self Test? */ +#define MBOX_POST_P(letter) ((letter) >= 0x00 && (letter) <= 0x7f) + +/* Is the cpu at the 'ok' prompt of the PROM? */ +#define MBOX_PROMPROMPT_P(letter) ((letter) >= 0x80 && (letter) <= 0x8f) + +/* Is the cpu spinning in the PROM? */ +#define MBOX_PROMSPIN_P(letter) ((letter) >= 0x90 && (letter) <= 0xef) + +/* Sanity check... This is junk mail, throw it out. */ +#define MBOX_BOGON_P(letter) ((letter) >= 0xf1 && (letter) <= 0xfa) + +/* Is the cpu actively running an application/kernel-code? */ +#define MBOX_RUNNING_P(letter) ((letter) == MAILBOX_ISRUNNING) + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_SPARC_MPMBOX_H) */ diff --git a/include/asm-sparc/msi.h b/include/asm-sparc/msi.h new file mode 100644 index 000000000..b69543dd3 --- /dev/null +++ b/include/asm-sparc/msi.h @@ -0,0 +1,31 @@ +/* $Id: msi.h,v 1.3 1996/08/29 09:48:25 davem Exp $ + * msi.h: Defines specific to the MBus - Sbus - Interface. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef _SPARC_MSI_H +#define _SPARC_MSI_H + +/* + * Locations of MSI Registers. + */ +#define MSI_MBUS_ARBEN 0xe0001008 /* MBus Arbiter Enable register */ + +/* + * Useful bits in the MSI Registers. + */ +#define MSI_ASYNC_MODE 0x80000000 /* Operate the MSI asynchronously */ + + +extern __inline__ void msi_set_sync(void) +{ + __asm__ __volatile__ ("lda [%0] %1, %%g3\n\t" + "andn %%g3, %2, %%g3\n\t" + "sta %%g3, [%0] %1\n\t" : : + "r" (MSI_MBUS_ARBEN), + "i" (ASI_M_CTL), "r" (MSI_ASYNC_MODE) : "g3"); +} + +#endif /* !(_SPARC_MSI_H) */ diff --git a/include/asm-sparc/mxcc.h b/include/asm-sparc/mxcc.h new file mode 100644 index 000000000..87947bc0f --- /dev/null +++ b/include/asm-sparc/mxcc.h @@ -0,0 +1,133 @@ +/* $Id: mxcc.h,v 1.6 1996/08/29 09:48:27 davem Exp $ + * mxcc.h: Definitions of the Viking MXCC registers + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_MXCC_H +#define _SPARC_MXCC_H + +/* These registers are accessed through ASI 0x2. */ +#define MXCC_DATSTREAM 0x1C00000 /* Data stream register */ +#define MXCC_SRCSTREAM 0x1C00100 /* Source stream register */ +#define MXCC_DESSTREAM 0x1C00200 /* Destination stream register */ +#define MXCC_RMCOUNT 0x1C00300 /* Count of references and misses */ +#define MXCC_STEST 0x1C00804 /* Internal self-test */ +#define MXCC_CREG 0x1C00A04 /* Control register */ +#define MXCC_SREG 0x1C00B00 /* Status register */ +#define MXCC_RREG 0x1C00C04 /* Reset register */ +#define MXCC_EREG 0x1C00E00 /* Error code register */ +#define MXCC_PREG 0x1C00F04 /* Address port register */ + +/* Some MXCC constants. */ +#define MXCC_STREAM_SIZE 0x20 /* Size in bytes of one stream r/w */ + +/* The MXCC Control Register: + * + * ---------------------------------------------------------------------- + * | | RRC | RSV |PRE|MCE|PARE|ECE|RSV| + * ---------------------------------------------------------------------- + * 31 10 9 8-6 5 4 3 2 1-0 + * + * RRC: Controls what you read from MXCC_RMCOUNT reg. + * 0=Misses 1=References + * PRE: Prefetch enable + * MCE: Multiple Command Enable + * PARE: Parity enable + * ECE: External cache enable + */ + +#define MXCC_CTL_RRC 0x00000200 +#define MXCC_CTL_PRE 0x00000020 +#define MXCC_CTL_MCE 0x00000010 +#define MXCC_CTL_PARE 0x00000008 +#define MXCC_CTL_ECE 0x00000004 + +/* The MXCC Error Register: + * + * -------------------------------------------------------- + * |ME| RSV|CE|PEW|PEE|ASE|EIV| MOPC|ECODE|PRIV|RSV|HPADDR| + * -------------------------------------------------------- + * 31 30 29 28 27 26 25 24-15 14-7 6 5-3 2-0 + * + * ME: Multiple Errors have occurred + * CE: Cache consistency Error + * PEW: Parity Error during a Write operation + * PEE: Parity Error involving the External cache + * ASE: ASynchronous Error + * EIV: This register is toast + * MOPC: MXCC Operation Code for instance causing error + * ECODE: The Error CODE + * PRIV: A privileged mode error? 0=no 1=yes + * HPADDR: High PhysicalADDRess bits (35-32) + */ + +#define MXCC_ERR_ME 0x80000000 +#define MXCC_ERR_CE 0x20000000 +#define MXCC_ERR_PEW 0x10000000 +#define MXCC_ERR_PEE 0x08000000 +#define MXCC_ERR_ASE 0x04000000 +#define MXCC_ERR_EIV 0x02000000 +#define MXCC_ERR_MOPC 0x01FF8000 +#define MXCC_ERR_ECODE 0x00007F80 +#define MXCC_ERR_PRIV 0x00000040 +#define MXCC_ERR_HPADDR 0x0000000f + +/* The MXCC Port register: + * + * ----------------------------------------------------- + * | | MID | | + * ----------------------------------------------------- + * 31 21 20-18 17 0 + * + * MID: The moduleID of the cpu your read this from. + */ + +extern __inline__ void mxcc_set_stream_src(unsigned long *paddr) +{ + unsigned long data0 = paddr[0]; + unsigned long data1 = paddr[1]; + + __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t" + "or %%g0, %1, %%g3\n\t" + "stda %%g2, [%2] %3\n\t" : : + "r" (data0), "r" (data1), + "r" (MXCC_SRCSTREAM), + "i" (ASI_M_MXCC) : "g2", "g3"); +} + +extern __inline__ void mxcc_set_stream_dst(unsigned long *paddr) +{ + unsigned long data0 = paddr[0]; + unsigned long data1 = paddr[1]; + + __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t" + "or %%g0, %1, %%g3\n\t" + "stda %%g2, [%2] %3\n\t" : : + "r" (data0), "r" (data1), + "r" (MXCC_DESSTREAM), + "i" (ASI_M_MXCC) : "g2", "g3"); +} + +extern __inline__ unsigned long mxcc_get_creg(void) +{ + unsigned long mxcc_control; + + __asm__ __volatile__("set -1, %%g2\n\t" + "set -1, %%g3\n\t" + "stda %%g2, [%1] %2\n\t" + "lda [%3] %2, %0\n\t" : + "=r" (mxcc_control) : + "r" (MXCC_EREG), "i" (ASI_M_MXCC), + "r" (MXCC_CREG) : "g2", "g3"); + return mxcc_control; +} + +extern __inline__ void mxcc_set_creg(unsigned long mxcc_control) +{ + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (mxcc_control), "r" (MXCC_CREG), + "i" (ASI_M_MXCC)); +} + +#endif /* !(_SPARC_MXCC_H) */ diff --git a/include/asm-sparc/openprom.h b/include/asm-sparc/openprom.h index ca6d9e36d..34f5d3c33 100644 --- a/include/asm-sparc/openprom.h +++ b/include/asm-sparc/openprom.h @@ -1,304 +1,210 @@ +/* $Id: openprom.h,v 1.19 1996/09/25 03:51:08 davem Exp $ */ #ifndef __SPARC_OPENPROM_H #define __SPARC_OPENPROM_H /* openprom.h: Prom structures and defines for access to the OPENBOOT - prom routines and data areas. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ + * prom routines and data areas. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ -/* In the v0 interface of the openboot prom we could traverse a nice - little list structure to figure out where in vm-space the prom had - mapped itself and how much space it was taking up. In the v2 prom - interface we have to rely on 'magic' values. :-( Most of the machines - I have checked on have the prom mapped here all the time though. -*/ +/* Empirical constants... */ +#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */ #define LINUX_OPPROM_BEGVM 0xffd00000 #define LINUX_OPPROM_ENDVM 0xfff00000 - #define LINUX_OPPROM_MAGIC 0x10010407 -/* The device functions structure for the v0 prom. Nice and neat, open, - close, read & write divvied up between net + block + char devices. We - also have a seek routine only usable for block devices. The divide - and conquer strategy of this struct becomes unnecessary for v2. - - V0 device names are limited to two characters, 'sd' for scsi-disk, - 'le' for local-ethernet, etc. Note that it is technically possible - to boot a kernel off of a tape drive and use the tape as the root - partition! In order to do this you have to have 'magic' formatted - tapes from Sun supposedly :-) -*/ - +#ifndef __ASSEMBLY__ +/* V0 prom device operations. */ struct linux_dev_v0_funcs { - int (*v0_devopen)(char *device_str); - int (*v0_devclose)(int dev_desc); - int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char* buf); - int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char* buf); - int (*v0_wrnetdev)(int dev_desc, int num_bytes, char* buf); - int (*v0_rdnetdev)(int dev_desc, int num_bytes, char* buf); - int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char* buf); - int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char* buf); - int (*v0_seekdev)(int dev_desc, long logical_offst, int from); + int (*v0_devopen)(char *device_str); + int (*v0_devclose)(int dev_desc); + int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_seekdev)(int dev_desc, long logical_offst, int from); }; -/* The OpenBoot Prom device operations for version-2 interfaces are both - good and bad. They now allow you to address ANY device whatsoever - that is in the machine via these funny "device paths". They look like - this: - - "/sbus/esp@0,0xf004002c/sd@3,1" - - You can basically reference any device on the machine this way, and - you pass this string to the v2 dev_ops. Producing these strings all - the time can be a pain in the rear after a while. Why v2 has memory - allocations in here are beyond me. Perhaps they figure that if you - are going to use only the prom's device drivers then your memory - management is either non-existent or pretty sad. :-) -*/ - +/* V2 and later prom device operations. */ struct linux_dev_v2_funcs { - int (*v2_aieee)(int d); /* figure this out later... */ - - /* "dumb" prom memory management routines, probably - only safe to use for mapping device address spaces... - */ - - char* (*v2_dumb_mem_alloc)(char* va, unsigned sz); - void (*v2_dumb_mem_free)(char* va, unsigned sz); - - /* "dumb" mmap() munmap(), copy on write? what's that? */ - char* (*v2_dumb_mmap)(char* virta, int asi, unsigned prot, unsigned sz); - void (*v2_dumb_munmap)(char* virta, unsigned size); - - /* Basic Operations, self-explanatory */ - int (*v2_dev_open)(char *devpath); - void (*v2_dev_close)(int d); - int (*v2_dev_read)(int d, char* buf, int nbytes); - int (*v2_dev_write)(int d, char* buf, int nbytes); - void (*v2_dev_seek)(int d, int hi, int lo); - - /* huh? */ - void (*v2_wheee2)(void); - void (*v2_wheee3)(void); + int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */ + char * (*v2_dumb_mem_alloc)(char *va, unsigned sz); + void (*v2_dumb_mem_free)(char *va, unsigned sz); + + /* To map devices into virtual I/O space. */ + char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz); + void (*v2_dumb_munmap)(char *virta, unsigned size); + + int (*v2_dev_open)(char *devpath); + void (*v2_dev_close)(int d); + int (*v2_dev_read)(int d, char *buf, int nbytes); + int (*v2_dev_write)(int d, char *buf, int nbytes); + int (*v2_dev_seek)(int d, int hi, int lo); + + /* Never issued (multistage load support) */ + void (*v2_wheee2)(void); + void (*v2_wheee3)(void); }; -/* Just like the device ops, they slightly screwed up the mem-list - from v0 to v2. Probably easier on the prom-writer dude, sucks for - us though. See above comment about prom-vm mapped address space - magic numbers. :-( -*/ - struct linux_mlist_v0 { - struct linux_mlist_v0 *theres_more; - char* start_adr; + struct linux_mlist_v0 *theres_more; + char *start_adr; unsigned num_bytes; }; -/* The linux_mlist_v0's are pointer by this structure. One list - per description. This means one list for total physical memory, - one for prom's address mapping, and one for physical mem left after - the kernel is loaded. - */ struct linux_mem_v0 { - struct linux_mlist_v0 **v0_totphys; /* all of physical */ - struct linux_mlist_v0 **v0_prommap; /* addresses map'd by prom */ - struct linux_mlist_v0 **v0_available; /* what phys. is left over */ + struct linux_mlist_v0 **v0_totphys; + struct linux_mlist_v0 **v0_prommap; + struct linux_mlist_v0 **v0_available; /* What we can use */ }; /* Arguments sent to the kernel from the boot prompt. */ - struct linux_arguments_v0 { - char *argv[8]; /* argv format for boot string */ - char args[100]; /* string space */ - char boot_dev[2]; /* e.g., "sd" for `b sd(...' */ - int boot_dev_ctrl; /* controller # */ - int boot_dev_unit; /* unit # */ - int dev_partition; /* partition # */ - char *kernel_file_name; /* kernel to boot, e.g., "vmunix" */ - void *aieee1; /* give me some time :> */ + char *argv[8]; + char args[100]; + char boot_dev[2]; + int boot_dev_ctrl; + int boot_dev_unit; + int dev_partition; + char *kernel_file_name; + void *aieee1; /* XXX */ }; -/* Prom version-2 gives us the raw strings for boot arguments and - boot device path. We also get the stdin and stdout file pseudo - descriptors for use with the mungy v2 device functions. -*/ +/* V2 and up boot things. */ struct linux_bootargs_v2 { - char **bootpath; /* V2: Path to boot device */ - char **bootargs; /* V2: Boot args */ - int *fd_stdin; /* V2: Stdin descriptor */ - int *fd_stdout; /* V2: Stdout descriptor */ + char **bootpath; + char **bootargs; + int *fd_stdin; + int *fd_stdout; }; -/* This is the actual Prom Vector from which everything else is accessed - via struct and function pointers, etc. The prom when it loads us into - memory plops a pointer to this master structure in register %o0 before - it jumps to the kernel start address. I will update this soon to cover - the v3 semantics (cpu_start, cpu_stop and other SMP fun things). :-) -*/ +/* The top level PROM vector. */ struct linux_romvec { /* Version numbers. */ - unsigned int pv_magic_cookie; /* Magic Mushroom... */ - unsigned int pv_romvers; /* iface vers (0, 2, or 3) */ - unsigned int pv_plugin_revision; /* revision relative to above vers */ - unsigned int pv_printrev; /* print revision */ - - /* Version 0 memory descriptors (see below). */ - struct linux_mem_v0 pv_v0mem; /* V0: Memory description lists. */ + unsigned int pv_magic_cookie; + unsigned int pv_romvers; + unsigned int pv_plugin_revision; + unsigned int pv_printrev; - /* Node operations (see below). */ - struct linux_nodeops *pv_nodeops; /* node functions, gets device data */ + /* Version 0 memory descriptors. */ + struct linux_mem_v0 pv_v0mem; - char **pv_bootstr; /* Boot command, eg sd(0,0,0)vmunix */ + /* Node operations. */ + struct linux_nodeops *pv_nodeops; - struct linux_dev_v0_funcs pv_v0devops; /* V0: device ops */ + char **pv_bootstr; + struct linux_dev_v0_funcs pv_v0devops; - /* - * PROMDEV_* cookies. I fear these may vanish in lieu of fd0/fd1 - * (see below) in future PROMs, but for now they work fine. - */ - char *pv_stdin; /* stdin cookie */ - char *pv_stdout; /* stdout cookie */ + char *pv_stdin; + char *pv_stdout; #define PROMDEV_KBD 0 /* input from keyboard */ #define PROMDEV_SCREEN 0 /* output to screen */ #define PROMDEV_TTYA 1 /* in/out to ttya */ #define PROMDEV_TTYB 2 /* in/out to ttyb */ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */ - int (*pv_getchar)(void); - void (*pv_putchar)(int ch); + int (*pv_getchar)(void); + void (*pv_putchar)(int ch); - /* Non-blocking variants that return -1 on error. */ - int (*pv_nbgetchar)(void); - int (*pv_nbputchar)(int ch); + /* Non-blocking variants. */ + int (*pv_nbgetchar)(void); + int (*pv_nbputchar)(int ch); - /* Put counted string (can be very slow). */ - void (*pv_putstr)(char *str, int len); + void (*pv_putstr)(char *str, int len); /* Miscellany. */ - void (*pv_reboot)(char *bootstr); - void (*pv_printf)(const char *fmt, ...); - void (*pv_abort)(void); /* BREAK key abort */ - int *pv_ticks; /* milliseconds since last reset */ - void (*pv_halt)(void); /* End the show */ - void (**pv_synchook)(void); /* "sync" ptr to function */ - - /* - * This eval's a FORTH string. Unfortunately, its interface - * changed between V0 and V2, which gave us much pain. - */ + void (*pv_reboot)(char *bootstr); + void (*pv_printf)(__const__ char *fmt, ...); + void (*pv_abort)(void); + __volatile__ int *pv_ticks; + void (*pv_halt)(void); + void (**pv_synchook)(void); + + /* Evaluate a forth string, not different proto for V0 and V2->up. */ union { - void (*v0_eval)(int len, char *str); - void (*v2_eval)(char *str); + void (*v0_eval)(int len, char *str); + void (*v2_eval)(char *str); } pv_fortheval; - struct linux_arguments_v0 **pv_v0bootargs; /* V0: Boot args */ + struct linux_arguments_v0 **pv_v0bootargs; - /* Extract Ethernet address from network device. */ - unsigned int (*pv_enaddr)(int d, char *enaddr); + /* Get ether address. */ + unsigned int (*pv_enaddr)(int d, char *enaddr); - struct linux_bootargs_v2 pv_v2bootargs; /* V2: Boot args+std-in/out */ - struct linux_dev_v2_funcs pv_v2devops; /* V2: device operations */ + struct linux_bootargs_v2 pv_v2bootargs; + struct linux_dev_v2_funcs pv_v2devops; - int whatzthis[15]; /* huh? */ + int filler[15]; - /* - * The following is machine-dependent. - * - * The sun4c needs a PROM function to set a PMEG for another - * context, so that the kernel can map itself in all contexts. - * It is not possible simply to set the context register, because - * contexts 1 through N may have invalid translations for the - * current program counter. The hardware has a mode in which - * all memory references go to the PROM, so the PROM can do it - * easily. - */ - void (*pv_setctxt)(int ctxt, char* va, int pmeg); + /* This one is sun4c/sun4 only. */ + void (*pv_setctxt)(int ctxt, char *va, int pmeg); /* Prom version 3 Multiprocessor routines. This stuff is crazy. * No joke. Calling these when there is only one cpu probably * crashes the machine, have to test this. :-) - */ + */ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context * 'thiscontext' executing at address 'prog_counter' - * - * XXX Have to figure out what 'cancontext' means. - */ - - int (*v3_cpustart)(unsigned int whichcpu, int cancontext, - int thiscontext, char* prog_counter); + */ + int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr, + int thiscontext, char *prog_counter); /* v3_cpustop() will cause cpu 'whichcpu' to stop executing * until a resume cpu call is made. */ - int (*v3_cpustop)(unsigned int whichcpu); /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or * resume cpu call is made. */ - int (*v3_cpuidle)(unsigned int whichcpu); /* v3_cpuresume() will resume processor 'whichcpu' executing * starting with whatever 'pc' and 'npc' were left at the * last 'idle' or 'stop' call. */ - int (*v3_cpuresume)(unsigned int whichcpu); +}; +/* Routines for traversing the prom device tree. */ +struct linux_nodeops { + int (*no_nextnode)(int node); + int (*no_child)(int node); + int (*no_proplen)(int node, char *name); + int (*no_getprop)(int node, char *name, char *val); + int (*no_setprop)(int node, char *name, char *val, int len); + char * (*no_nextprop)(int node, char *name); }; -/* - * In addition to the global stuff defined in the PROM vectors above, - * the PROM has quite a collection of `nodes'. A node is described by - * an integer---these seem to be internal pointers, actually---and the - * nodes are arranged into an N-ary tree. Each node implements a fixed - * set of functions, as described below. The first two deal with the tree - * structure, allowing traversals in either breadth- or depth-first fashion. - * The rest deal with `properties'. - * - * A node property is simply a name/value pair. The names are C strings - * (NUL-terminated); the values are arbitrary byte strings (counted strings). - * Many values are really just C strings. Sometimes these are NUL-terminated, - * sometimes not, depending on the the interface version; v0 seems to - * terminate and v2 not. Many others are simply integers stored as four - * bytes in machine order: you just get them and go. The third popular - * format is an `address', which is made up of one or more sets of three - * integers as defined below. - * - * One uses these functions to traverse the device tree to see what devices - * this machine has attached to it. - * - * N.B.: for the `next' functions, next(0) = first, and next(last) = 0. - * Whoever designed this part had good taste. On the other hand, these - * operation vectors are global, rather than per-node, yet the pointers - * are not in the openprom vectors but rather found by indirection from - * there. So the taste balances out. - */ -struct linux_prom_addr { - int oa_space; /* address space (may be relative) */ - unsigned int oa_base; /* address within space */ - unsigned int oa_size; /* extent (number of bytes) */ +/* More fun PROM structures for device probing. */ +#define PROMREG_MAX 16 +#define PROMVADDR_MAX 16 +#define PROMINTR_MAX 15 + +struct linux_prom_registers { + int which_io; /* is this in OBIO space? */ + char *phys_addr; /* The physical address of this register */ + int reg_size; /* How many bytes does this register take up? */ }; -struct linux_nodeops { - /* - * Tree traversal. - */ - int (*no_nextnode)(int node); /* next(node) */ - int (*no_child)(int node); /* first child */ +struct linux_prom_irqs { + int pri; /* IRQ priority */ + int vector; /* This is foobar, what does it do? */ +}; - /* - * Property functions. Proper use of getprop requires calling - * proplen first to make sure it fits. Kind of a pain, but no - * doubt more convenient for the PROM coder. - */ - int (*no_proplen)(int node, char* name); - int (*no_getprop)(int node, char* name, char* val); - int (*no_setprop)(int node, char* name, char* val, int len); - char* (*no_nextprop)(int node, char* name); +/* Element of the "ranges" vector */ +struct linux_prom_ranges { + unsigned int ot_child_space; + unsigned int ot_child_base; /* Bus feels this */ + unsigned int ot_parent_space; + unsigned int ot_parent_base; /* CPU looks from here */ + unsigned int or_size; }; +#endif /* !(__ASSEMBLY__) */ + #endif /* !(__SPARC_OPENPROM_H) */ diff --git a/include/asm-sparc/openpromio.h b/include/asm-sparc/openpromio.h new file mode 100644 index 000000000..8989909de --- /dev/null +++ b/include/asm-sparc/openpromio.h @@ -0,0 +1,70 @@ +#ifndef _SPARC_OPENPROMIO_H +#define _SPARC_OPENPROMIO_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +/* + * SunOS and Solaris /dev/openprom definitions. The ioctl values + * were chosen to be exactly equal to the SunOS equivalents. + */ + +struct openpromio +{ + u_int oprom_size; /* Actual size of the oprom_array. */ + char oprom_array[1]; /* Holds property names and values. */ +}; + +#define OPROMMAXPARAM 4096 /* Maximum size of oprom_array. */ + +#define OPROMGETOPT 0x20004F01 +#define OPROMSETOPT 0x20004F02 +#define OPROMNXTOPT 0x20004F03 +#define OPROMSETOPT2 0x20004F04 +#define OPROMNEXT 0x20004F05 +#define OPROMCHILD 0x20004F06 +#define OPROMGETPROP 0x20004F07 +#define OPROMNXTPROP 0x20004F08 +#define OPROMU2P 0x20004F09 +#define OPROMGETCONS 0x20004F0A +#define OPROMGETFBNAME 0x20004F0B +#define OPROMGETBOOTARGS 0x20004F0C + +/* + * Return values from OPROMGETCONS: + */ + +#define OPROMCONS_NOT_WSCONS 0 +#define OPROMCONS_STDIN_IS_KBD 0x1 /* stdin device is kbd */ +#define OPROMCONS_STDOUT_IS_FB 0x2 /* stdout is a framebuffer */ +#define OPROMCONS_OPENPROM 0x4 /* supports openboot */ + + +/* + * NetBSD/OpenBSD /dev/openprom definitions. + */ + +struct opiocdesc +{ + int op_nodeid; /* PROM Node ID (value-result) */ + int op_namelen; /* Length of op_name. */ + char *op_name; /* Pointer to the property name. */ + int op_buflen; /* Length of op_buf (value-result) */ + char *op_buf; /* Pointer to buffer. */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) +#define OPIOCSET _IOW('O', 2, struct opiocdesc) +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) +#define OPIOCGETOPTNODE _IOR('O', 4, int) +#define OPIOCGETNEXT _IOWR('O', 5, int) +#define OPIOCGETCHILD _IOWR('O', 6, int) + + +#ifdef __KERNEL__ +int openprom_init(void); +#endif + + +#endif /* _SPARC_OPENPROMIO_H */ + diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h new file mode 100644 index 000000000..84248e0eb --- /dev/null +++ b/include/asm-sparc/oplib.h @@ -0,0 +1,297 @@ +/* $Id: oplib.h,v 1.12 1996/10/31 06:29:13 davem Exp $ + * oplib.h: Describes the interface and available routines in the + * Linux Prom library. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __SPARC_OPLIB_H +#define __SPARC_OPLIB_H + +#include <asm/openprom.h> + +/* The master romvec pointer... */ +extern struct linux_romvec *romvec; + +/* Enumeration to describe the prom major version we have detected. */ +enum prom_major_version { + PROM_V0, /* Original sun4c V0 prom */ + PROM_V2, /* sun4c and early sun4m V2 prom */ + PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */ + PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */ + PROM_AP1000, /* actually no prom at all */ +}; + +extern enum prom_major_version prom_vers; +/* Revision, and firmware revision. */ +extern unsigned int prom_rev, prom_prev; + +/* Root node of the prom device tree, this stays constant after + * initialization is complete. + */ +extern int prom_root_node; + +/* Pointer to prom structure containing the device tree traversal + * and usage utility functions. Only prom-lib should use these, + * users use the interface defined by the library only! + */ +extern struct linux_nodeops *prom_nodeops; + +/* The functions... */ + +/* You must call prom_init() before using any of the library services, + * preferably as early as possible. Pass it the romvec pointer. + */ +extern void prom_init(struct linux_romvec *rom_ptr); + +/* Boot argument acquisition, returns the boot command line string. */ +extern char *prom_getbootargs(void); + +/* Device utilities. */ + +/* Map and unmap devices in IO space at virtual addresses. Note that the + * virtual address you pass is a request and the prom may put your mappings + * somewhere else, so check your return value as that is where your new + * mappings really are! + * + * Another note, these are only available on V2 or higher proms! + */ +extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes); +extern void prom_unmapio(char *virt_addr, unsigned int num_bytes); + +/* Device operations. */ + +/* Open the device described by the passed string. Note, that the format + * of the string is different on V0 vs. V2->higher proms. The caller must + * know what he/she is doing! Returns the device descriptor, an int. + */ +extern int prom_devopen(char *device_string); + +/* Close a previously opened device described by the passed integer + * descriptor. + */ +extern int prom_devclose(int device_handle); + +/* Do a seek operation on the device described by the passed integer + * descriptor. + */ +extern void prom_seek(int device_handle, unsigned int seek_hival, + unsigned int seek_lowval); + +/* Machine memory configuration routine. */ + +/* This function returns a V0 format memory descriptor table, it has three + * entries. One for the total amount of physical ram on the machine, one + * for the amount of physical ram available, and one describing the virtual + * areas which are allocated by the prom. So, in a sense the physical + * available is a calculation of the total physical minus the physical mapped + * by the prom with virtual mappings. + * + * These lists are returned pre-sorted, this should make your life easier + * since the prom itself is way too lazy to do such nice things. + */ +extern struct linux_mem_v0 *prom_meminfo(void); + +/* Miscellaneous routines, don't really fit in any category per se. */ + +/* Reboot the machine with the command line passed. */ +extern void prom_reboot(char *boot_command); + +/* Evaluate the forth string passed. */ +extern void prom_feval(char *forth_string); + +/* Enter the prom, with possibility of continuation with the 'go' + * command in newer proms. + */ +extern void prom_cmdline(void); + +/* Enter the prom, with no chance of continuation for the stand-alone + * which calls this. + */ +extern void prom_halt(void); + +/* Set the PROM 'sync' callback function to the passed function pointer. + * When the user gives the 'sync' command at the prom prompt while the + * kernel is still active, the prom will call this routine. + * + * XXX The arguments are different on V0 vs. V2->higher proms, grrr! XXX + */ +typedef void (*sync_func_t)(void); +extern void prom_setsync(sync_func_t func_ptr); + +/* Acquire the IDPROM of the root node in the prom device tree. This + * gets passed a buffer where you would like it stuffed. The return value + * is the format type of this idprom or 0xff on error. + */ +extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); + +/* Get the prom major version. */ +extern int prom_version(void); + +/* Get the prom plugin revision. */ +extern int prom_getrev(void); + +/* Get the prom firmware revision. */ +extern int prom_getprev(void); + +/* Character operations to/from the console.... */ + +/* Non-blocking get character from console. */ +extern int prom_nbgetchar(void); + +/* Non-blocking put character to console. */ +extern int prom_nbputchar(char character); + +/* Blocking get character from console. */ +extern char prom_getchar(void); + +/* Blocking put character to console. */ +extern void prom_putchar(char character); + +/* Prom's internal printf routine, don't use in kernel/boot code. */ +void prom_printf(char *fmt, ...); + +/* Query for input device type */ + +enum prom_input_device { + PROMDEV_IKBD, /* input from keyboard */ + PROMDEV_ITTYA, /* input from ttya */ + PROMDEV_ITTYB, /* input from ttyb */ + PROMDEV_I_UNK, +}; + +extern enum prom_input_device prom_query_input_device(void); + +/* Query for output device type */ + +enum prom_output_device { + PROMDEV_OSCREEN, /* to screen */ + PROMDEV_OTTYA, /* to ttya */ + PROMDEV_OTTYB, /* to ttyb */ + PROMDEV_O_UNK, +}; + +extern enum prom_output_device prom_query_output_device(void); + +/* Multiprocessor operations... */ + +/* Start the CPU with the given device tree node, context table, and context + * at the passed program counter. + */ +extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table, + int context, char *program_counter); + +/* Stop the CPU with the passed device tree node. */ +extern int prom_stopcpu(int cpunode); + +/* Idle the CPU with the passed device tree node. */ +extern int prom_idlecpu(int cpunode); + +/* Re-Start the CPU with the passed device tree node. */ +extern int prom_restartcpu(int cpunode); + +/* PROM memory allocation facilities... */ + +/* Allocated at possibly the given virtual address a chunk of the + * indicated size. + */ +extern char *prom_alloc(char *virt_hint, unsigned int size); + +/* Free a previously allocated chunk. */ +extern void prom_free(char *virt_addr, unsigned int size); + +/* Sun4/sun4c specific memory-management startup hook. */ + +/* Map the passed segment in the given context at the passed + * virtual address. + */ +extern void prom_putsegment(int context, unsigned long virt_addr, + int physical_segment); + +/* PROM device tree traversal functions... */ + +/* Get the child node of the given node, or zero if no child exists. */ +extern int prom_getchild(int parent_node); + +/* Get the next sibling node of the given node, or zero if no further + * siblings exist. + */ +extern int prom_getsibling(int node); + +/* Get the length, at the passed node, of the given property type. + * Returns -1 on error (ie. no such property at this node). + */ +extern int prom_getproplen(int thisnode, char *property); + +/* Fetch the requested property using the given buffer. Returns + * the number of bytes the prom put into your buffer or -1 on error. + */ +extern int prom_getproperty(int thisnode, char *property, + char *prop_buffer, int propbuf_size); + +/* Acquire an integer property. */ +extern int prom_getint(int node, char *property); + +/* Acquire an integer property, with a default value. */ +extern int prom_getintdefault(int node, char *property, int defval); + +/* Acquire a boolean property, 0=FALSE 1=TRUE. */ +extern int prom_getbool(int node, char *prop); + +/* Acquire a string property, null string on error. */ +extern void prom_getstring(int node, char *prop, char *buf, int bufsize); + +/* Does the passed node have the given "name"? YES=1 NO=0 */ +extern int prom_nodematch(int thisnode, char *name); + +/* Puts in buffer a prom name in the form name@x,y or name (x for which_io + * and y for first regs phys address + */ +extern int prom_getname(int node, char *buf, int buflen); + +/* Search all siblings starting at the passed node for "name" matching + * the given string. Returns the node on success, zero on failure. + */ +extern int prom_searchsiblings(int node_start, char *name); + +/* Return the first property type, as a string, for the given node. + * Returns a null string on error. + */ +extern char *prom_firstprop(int node); + +/* Returns the next property after the passed property for the given + * node. Returns null string on failure. + */ +extern char *prom_nextprop(int node, char *prev_property); + +/* Returns 1 if the specified node has given property. */ +extern int prom_node_has_property(int node, char *property); + +/* Set the indicated property at the given node with the passed value. + * Returns the number of bytes of your value that the prom took. + */ +extern int prom_setprop(int node, char *prop_name, char *prop_value, + int value_size); + +extern int prom_pathtoinode(char *path); +extern int prom_inst2pkg(int); + +/* Dorking with Bus ranges... */ + +/* Adjust reg values with the passed ranges. */ +extern void prom_adjust_regs(struct linux_prom_registers *regp, int nregs, + struct linux_prom_ranges *rangep, int nranges); + +/* Adjust child ranges with the passed parent ranges. */ +extern void prom_adjust_ranges(struct linux_prom_ranges *cranges, int ncranges, + struct linux_prom_ranges *pranges, int npranges); + +/* Apply promlib probed OBIO ranges to registers. */ +extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs); + +/* Apply ranges of any prom node (and optionally parent node as well) to registers. */ +extern void prom_apply_generic_ranges(int node, int parent, + struct linux_prom_registers *sbusregs, int nregs); + + +#endif /* !(__SPARC_OPLIB_H) */ diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h index a048ac76c..43bbf1847 100644 --- a/include/asm-sparc/page.h +++ b/include/asm-sparc/page.h @@ -1,31 +1,42 @@ -/* page.h: Various defines and such for MMU operations on the Sparc for - the Linux kernel. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ +/* $Id: page.h,v 1.30 1996/10/27 08:55:30 davem Exp $ + * page.h: Various defines and such for MMU operations on the Sparc for + * the Linux kernel. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ #ifndef _SPARC_PAGE_H #define _SPARC_PAGE_H -#include <asm/asi.h> /* for get/set segmap/pte routines */ -#include <asm/contregs.h> /* for switch_to_context */ +#include <asm/head.h> /* for KERNBASE */ -#define PAGE_SHIFT 12 /* This is the virtual page... */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) +#ifdef __KERNEL__ #ifndef __ASSEMBLY__ -#define PAGE_SIZE (1UL << PAGE_SHIFT) -/* to mask away the intra-page address bits */ -#define PAGE_MASK (~(PAGE_SIZE-1)) +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) -#ifdef __KERNEL__ +extern unsigned long page_offset; + +#define PAGE_OFFSET (page_offset) + +/* translate between physical and virtual addresses */ +extern unsigned long (*mmu_v2p)(unsigned long); +extern unsigned long (*mmu_p2v)(unsigned long); + +#define __pa(x) mmu_v2p(x) +#define __va(x) mmu_p2v(x) /* The following structure is used to hold the physical - * memory configuration of the machine. This is filled - * in probe_memory() and is later used by mem_init() to - * set up mem_map[]. We statically allocate 14 of these - * structs, this is arbitrary. The entry after the last - * valid one has num_bytes==0. + * memory configuration of the machine. This is filled in + * probe_memory() and is later used by mem_init() to set up + * mem_map[]. We statically allocate SPARC_PHYS_BANKS of + * these structs, this is arbitrary. The entry after the + * last valid one has num_bytes==0. */ struct sparc_phys_banks { @@ -33,148 +44,95 @@ struct sparc_phys_banks { unsigned long num_bytes; }; -#define CONFIG_STRICT_MM_TYPECHECKS +#define SPARC_PHYS_BANKS 32 + +extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; + +/* Cache alias structure. Entry is valid if context != -1. */ +struct cache_palias { + unsigned long vaddr; + int context; +}; + +extern struct cache_palias *sparc_aliases; -#ifdef CONFIG_STRICT_MM_TYPECHECKS +/* passing structs on the Sparc slow us down tremendously... */ + +/* #define STRICT_MM_TYPECHECKS */ + +#ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. */ typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long iopte; } iopte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long ctxd; } ctxd_t; typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct { unsigned long iopgprot; } iopgprot_t; #define pte_val(x) ((x).pte) +#define iopte_val(x) ((x).iopte) #define pmd_val(x) ((x).pmd) #define pgd_val(x) ((x).pgd) +#define ctxd_val(x) ((x).ctxd) #define pgprot_val(x) ((x).pgprot) +#define iopgprot_val(x) ((x).iopgprot) #define __pte(x) ((pte_t) { (x) } ) +#define __iopte(x) ((iopte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) +#define __ctxd(x) ((ctxd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) +#define __iopgprot(x) ((iopgprot_t) { (x) } ) #else /* * .. while these make it easier on the compiler */ typedef unsigned long pte_t; +typedef unsigned long iopte_t; typedef unsigned long pmd_t; typedef unsigned long pgd_t; +typedef unsigned long ctxd_t; typedef unsigned long pgprot_t; +typedef unsigned long iopgprot_t; #define pte_val(x) (x) +#define iopte_val(x) (x) #define pmd_val(x) (x) #define pgd_val(x) (x) +#define ctxd_val(x) (x) #define pgprot_val(x) (x) +#define iopgprot_val(x) (x) #define __pte(x) (x) +#define __iopte(x) (x) #define __pmd(x) (x) #define __pgd(x) (x) +#define __ctxd(x) (x) #define __pgprot(x) (x) +#define __iopgprot(x) (x) #endif -/* The current va context is global and known, so all that is needed to - * do an invalidate is flush the VAC. - */ +#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE) -#define invalidate() flush_vac_context() /* how conveeeiiiiinnnient :> */ +extern unsigned long sparc_unmapped_base; -#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE) +#define TASK_UNMAPPED_BASE (sparc_unmapped_base) /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -#define PAGE_OFFSET 0 -#define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT) -#define MAP_PAGE_RESERVED (1<<15) - - -#endif /* !(__ASSEMBLY__) */ - -/* The rest is kind of funky because on the sparc, the offsets into the mmu - * entries are encoded in magic alternate address space tables. I will - * probably find some nifty inline assembly routines to do the equivalent. - * Much thought must go into this code. (davem@caip.rutgers.edu) +/* Now, to allow for very large physical memory configurations we + * place the page pool both above the kernel and below the kernel. */ +#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT) -/* Bitfields within a Sparc sun4c PTE (page table entry). */ - -#define PTE_V 0x80000000 /* valid bit */ -#define PTE_ACC 0x60000000 /* access bits */ -#define PTE_W 0x40000000 /* writable bit */ -#define PTE_P 0x20000000 /* privileged page */ -#define PTE_NC 0x10000000 /* page is non-cacheable */ -#define PTE_TYP 0x0c000000 /* page type field */ -#define PTE_RMEM 0x00000000 /* type == on board real memory */ -#define PTE_IO 0x04000000 /* type == i/o area */ -#define PTE_VME16 0x08000000 /* type == 16-bit VME area */ -#define PTE_VME32 0x0c000000 /* type == 32-bit VME area */ -#define PTE_R 0x02000000 /* page has been referenced */ -#define PTE_M 0x01000000 /* page has been modified */ -#define PTE_RESV 0x00f80000 /* reserved bits */ -#define PTE_PHYPG 0x0007ffff /* phys pg number, sun4c only uses 16bits */ - -extern __inline__ unsigned long get_segmap(unsigned long addr) -{ - register unsigned long entry; - - __asm__ __volatile__("lduba [%1] 0x3, %0" : - "=r" (entry) : - "r" (addr)); - - return (entry&0x7f); -} - -extern __inline__ void put_segmap(unsigned long addr, unsigned long entry) -{ - - __asm__ __volatile__("stba %1, [%0] 0x3" : : "r" (addr), "r" (entry&0x7f)); - - return; -} - -extern __inline__ unsigned long get_pte(unsigned long addr) -{ - register unsigned long entry; - - __asm__ __volatile__("lda [%1] 0x4, %0" : - "=r" (entry) : - "r" (addr)); - return entry; -} - -extern __inline__ void put_pte(unsigned long addr, unsigned long entry) -{ - __asm__ __volatile__("sta %1, [%0] 0x4" : : - "r" (addr), - "r" (entry)); - - return; -} - -extern __inline__ void switch_to_context(int context) -{ - __asm__ __volatile__("stba %0, [%1] 0x2" : : - "r" (context), - "r" (0x30000000)); - - return; -} - -extern __inline__ int get_context(void) -{ - register int ctx; - - __asm__ __volatile__("lduba [%1] 0x2, %0" : - "=r" (ctx) : - "r" (0x30000000)); - - return ctx; -} - -typedef unsigned short mem_map_t; +#endif /* !(__ASSEMBLY__) */ #endif /* __KERNEL__ */ diff --git a/include/asm-sparc/param.h b/include/asm-sparc/param.h index 45a9133af..7e14a410e 100644 --- a/include/asm-sparc/param.h +++ b/include/asm-sparc/param.h @@ -1,3 +1,4 @@ +/* $Id: param.h,v 1.3 1995/11/25 02:32:18 davem Exp $ */ #ifndef _ASMSPARC_PARAM_H #define _ASMSPARC_PARAM_H @@ -5,7 +6,7 @@ #define HZ 100 #endif -#define EXEC_PAGESIZE 4096 +#define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */ #ifndef NGROUPS #define NGROUPS 32 diff --git a/include/asm-sparc/pconf.h b/include/asm-sparc/pconf.h new file mode 100644 index 000000000..d73c1f1c4 --- /dev/null +++ b/include/asm-sparc/pconf.h @@ -0,0 +1,25 @@ +/* $Id: pconf.h,v 1.3 1996/04/25 06:13:25 davem Exp $ + * pconf.h: pathconf() and fpathconf() defines for SunOS + * system call compatibility. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_PCONF_H +#define _SPARC_PCONF_H + +#include <linux/fs.h> +#include <linux/limits.h> + +#define _PCONF_LINK 1 /* Max number of links to an object */ +#define _PCONF_CANON 2 /* TTY input buffer line size */ +#define _PCONF_INPUT 3 /* Biggest packet a tty can imbibe at once */ +#define _PCONF_NAME 4 /* Filename length max */ +#define _PCONF_PATH 5 /* Max size of a pathname */ +#define _PCONF_PIPE 6 /* Buffer size for a pipe */ +#define _PCONF_CHRESTRICT 7 /* Can only root chown files? */ +#define _PCONF_NOTRUNC 8 /* Are pathnames truncated if too big? */ +#define _PCONF_VDISABLE 9 /* Magic char to disable special tty chars */ +#define _PCONF_MAXPCONF 9 + +#endif /* !(_SPARC_PCONF_H) */ diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index 45b652108..02435d788 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -1,3 +1,4 @@ +/* $Id: pgtable.h,v 1.51 1996/10/27 08:55:32 davem Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -7,100 +8,133 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -/* PMD_SHIFT determines the size of the area a second-level page table can map */ -#define PMD_SHIFT 18 -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* PGDIR_SHIFT determines what a third-level page table entry can map */ -#define PGDIR_SHIFT 18 -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) -#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK) +#include <linux/mm.h> +#include <asm/asi.h> +#include <asm/pgtsun4c.h> +#include <asm/pgtsrmmu.h> +#include <asm/vac-ops.h> +#include <asm/oplib.h> +#include <asm/sbus.h> + +extern void load_mmu(void); +extern int io_remap_page_range(unsigned long from, unsigned long to, + unsigned long size, pgprot_t prot, int space); + +extern void (*quick_kernel_fault)(unsigned long); + +/* Allocate a block of RAM which is aligned to its size. + This procedure can be used until the call to mem_init(). */ +extern void *sparc_init_alloc(unsigned long *kbrk, unsigned long size); + +/* mmu-specific process creation/cloning/etc hooks. */ +extern void (*mmu_exit_hook)(void); +extern void (*mmu_flush_hook)(void); + +/* translate between physical and virtual addresses */ +extern unsigned long (*mmu_v2p)(unsigned long); +extern unsigned long (*mmu_p2v)(unsigned long); + +/* Routines for data transfer buffers. */ +extern char *(*mmu_lockarea)(char *, unsigned long); +extern void (*mmu_unlockarea)(char *, unsigned long); + +/* Routines for getting a dvma scsi buffer. */ +struct mmu_sglist { + char *addr; + char *__dont_touch; + unsigned int len; + char *dvma_addr; +}; +extern char *(*mmu_get_scsi_one)(char *, unsigned long, struct linux_sbus *sbus); +extern void (*mmu_get_scsi_sgl)(struct mmu_sglist *, int, struct linux_sbus *sbus); +extern void (*mmu_release_scsi_one)(char *, unsigned long, struct linux_sbus *sbus); +extern void (*mmu_release_scsi_sgl)(struct mmu_sglist *, int, struct linux_sbus *sbus); + +extern void (*mmu_map_dma_area)(unsigned long addr, int len); + +extern unsigned int pmd_shift; +extern unsigned int pmd_size; +extern unsigned int pmd_mask; +extern unsigned int (*pmd_align)(unsigned int); + +extern unsigned int pgdir_shift; +extern unsigned int pgdir_size; +extern unsigned int pgdir_mask; +extern unsigned int (*pgdir_align)(unsigned int); + +extern unsigned int ptrs_per_pte; +extern unsigned int ptrs_per_pmd; +extern unsigned int ptrs_per_pgd; + +extern unsigned int ptrs_per_page; + +extern unsigned long (*(vmalloc_start))(void); + +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) +#define VMALLOC_START vmalloc_start() + +extern pgprot_t page_none; +extern pgprot_t page_shared; +extern pgprot_t page_copy; +extern pgprot_t page_readonly; +extern pgprot_t page_kernel; + +#define PMD_SHIFT (pmd_shift) +#define PMD_SIZE (pmd_size) +#define PMD_MASK (pmd_mask) +#define PMD_ALIGN (pmd_align) +#define PGDIR_SHIFT (pgdir_shift) +#define PGDIR_SIZE (pgdir_size) +#define PGDIR_MASK (pgdir_mask) +#define PGDIR_ALIGN (pgdir_align) +#define PTRS_PER_PTE (ptrs_per_pte) +#define PTRS_PER_PMD (ptrs_per_pmd) +#define PTRS_PER_PGD (ptrs_per_pgd) + +#define PAGE_NONE (page_none) +#define PAGE_SHARED (page_shared) +#define PAGE_COPY (page_copy) +#define PAGE_READONLY (page_readonly) +#define PAGE_KERNEL (page_kernel) +#define PAGE_INVALID (page_invalid) + +/* Top-level page directory */ +extern pgd_t swapper_pg_dir[1024]; -/* - * Just following the i386 lead, because it works on the Sparc sun4c - * machines. Two-level, therefore there is no real PMD. +/* Page table for 0-4MB for everybody, on the Sparc this + * holds the same as on the i386. */ +extern pte_t pg0[1024]; -#define PTRS_PER_PTE 1024 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 1024 +extern unsigned long ptr_in_current_pgd; /* the no. of pointers that fit on a page: this will go away */ #define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*)) -/* Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x)) - -/* - * Sparc page table fields. - */ - -#define _PAGE_VALID 0x80000000 /* valid page */ -#define _PAGE_WRITE 0x40000000 /* can be written to */ -#define _PAGE_PRIV 0x20000000 /* bit to signify privileged page */ -#define _PAGE_NOCACHE 0x10000000 /* non-cacheable page */ -#define _PAGE_REF 0x02000000 /* Page has been accessed/referenced */ -#define _PAGE_DIRTY 0x01000000 /* Page has been modified, is dirty */ -#define _PAGE_COW 0x00800000 /* COW page, hardware ignores this bit (untested) */ - - -/* Sparc sun4c mmu has only a writable bit. Thus if a page is valid it can be - * read in a load, and executed as code automatically. Although, the memory fault - * hardware does make a distinction between date-read faults and insn-read faults - * which is determined by which trap happened plus magic sync/async fault register - * values which must be checked in the actual fault handler. +/* Here is a trick, since mmap.c need the initializer elements for + * protection_map[] to be constant at compile time, I set the following + * to all zeros. I set it to the real values after I link in the + * appropriate MMU page table routines at boot time. */ - -/* We want the swapper not to swap out page tables, thus dirty and writable - * so that the kernel can change the entries as needed. Also valid for - * obvious reasons. - */ -#define _PAGE_TABLE (_PAGE_VALID | _PAGE_WRITE | _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_REF | _PAGE_DIRTY) - -#define PAGE_NONE __pgprot(_PAGE_VALID | _PAGE_REF) -#define PAGE_SHARED __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_REF) -#define PAGE_COPY __pgprot(_PAGE_VALID | _PAGE_REF | _PAGE_COW) -#define PAGE_READONLY __pgprot(_PAGE_VALID | _PAGE_REF) -#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_NOCACHE | _PAGE_REF | _PAGE_PRIV) -#define PAGE_INVALID __pgprot(_PAGE_PRIV) - -#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | _PAGE_REF | (x)) - -/* I define these like the i386 does because the check for text or data fault - * is done at trap time by the low level handler. Maybe I can set these bits - * then once determined. I leave them like this for now though. - */ -#define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY -#define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY -#define __P110 PAGE_COPY -#define __P111 PAGE_COPY - -#define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY -#define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED - - -extern unsigned long pg0[1024]; +#define __P000 __pgprot(0) +#define __P001 __pgprot(0) +#define __P010 __pgprot(0) +#define __P011 __pgprot(0) +#define __P100 __pgprot(0) +#define __P101 __pgprot(0) +#define __P110 __pgprot(0) +#define __P111 __pgprot(0) + +#define __S000 __pgprot(0) +#define __S001 __pgprot(0) +#define __S010 __pgprot(0) +#define __S011 __pgprot(0) +#define __S100 __pgprot(0) +#define __S101 __pgprot(0) +#define __S110 __pgprot(0) +#define __S111 __pgprot(0) + +extern int num_contexts; /* * BAD_PAGETABLE is used when we need a bogus page-table, while @@ -112,231 +146,219 @@ extern unsigned long pg0[1024]; extern pte_t __bad_page(void); extern pte_t * __bad_pagetable(void); -extern unsigned long __zero_page(void); - +extern unsigned long empty_zero_page; #define BAD_PAGETABLE __bad_pagetable() #define BAD_PAGE __bad_page() -#define ZERO_PAGE __zero_page() +#define ZERO_PAGE ((unsigned long)(&(empty_zero_page))) /* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8*sizeof(unsigned long)) /* better check this stuff */ +#define BITS_PER_PTR (8*sizeof(unsigned long)) /* to align the pointer to a pointer address */ #define PTR_MASK (~(sizeof(void*)-1)) - #define SIZEOF_PTR_LOG2 2 +extern unsigned long (*pte_page)(pte_t); +extern unsigned long (*pmd_page)(pmd_t); +extern unsigned long (*pgd_page)(pgd_t); -/* to set the page-dir - * - * On the Sparc the page segments hold 64 pte's which means 256k/segment. - * Therefore there is no global idea of 'the' page directory, although we - * make a virtual one in kernel memory so that we can keep the stats on - * all the pages since not all can be loaded at once in the mmu. - */ - -#define SET_PAGE_DIR(tsk,pgdir) +extern void (*sparc_update_rootmmu_dir)(struct task_struct *, pgd_t *pgdir); +#define SET_PAGE_DIR(tsk,pgdir) sparc_update_rootmmu_dir(tsk, pgdir) + /* to find an entry in a page-table */ #define PAGE_PTR(address) \ ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -extern unsigned long high_memory; +extern int (*pte_none)(pte_t); +extern int (*pte_present)(pte_t); +extern void (*pte_clear)(pte_t *); -extern inline int pte_none(pte_t pte) { return !pte_val(pte); } -extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } -extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)] > 1; } -extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } -extern inline void pte_reuse(pte_t *ptep) -{ - if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED)) - mem_map[MAP_NR(ptep)]++; -} +extern int (*pmd_none)(pmd_t); +extern int (*pmd_bad)(pmd_t); +extern int (*pmd_present)(pmd_t); +extern void (*pmd_clear)(pmd_t *); -extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } -extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; } -extern inline int pmd_inuse(pmd_t *pmdp) { return 0; } -extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; } -extern inline void pmd_reuse(pmd_t * pmdp) { } - -extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; } -extern inline int pgd_inuse(pgd_t *pgdp) { return mem_map[MAP_NR(pgdp)] > 1; } -extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } -extern inline void pgd_reuse(pgd_t *pgdp) -{ - if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED)) - mem_map[MAP_NR(pgdp)]++; -} +extern int (*pgd_none)(pgd_t); +extern int (*pgd_bad)(pgd_t); +extern int (*pgd_present)(pgd_t); +extern void (*pgd_clear)(pgd_t *); /* * The following only work if pte_present() is true. * Undefined behaviour if not.. */ -extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } -extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_REF; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_REF; } -extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } - -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_VALID; return pte; } -extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_VALID; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_REF; return pte; } -extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; } -extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_VALID; return pte; } -extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_VALID; return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_REF; return pte; } -extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } +extern int (*pte_write)(pte_t); +extern int (*pte_dirty)(pte_t); +extern int (*pte_young)(pte_t); + +extern pte_t (*pte_wrprotect)(pte_t); +extern pte_t (*pte_mkclean)(pte_t); +extern pte_t (*pte_mkold)(pte_t); +extern pte_t (*pte_mkwrite)(pte_t); +extern pte_t (*pte_mkdirty)(pte_t); +extern pte_t (*pte_mkyoung)(pte_t); /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */ -extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) -{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } - -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } - -extern inline unsigned long pte_page(pte_t pte) { return pte_val(pte) & PAGE_MASK; } - -extern inline unsigned long pmd_page(pmd_t pmd) { return pmd_val(pmd) & PAGE_MASK; } - -extern inline unsigned long pgd_page(pgd_t pgd) { return pgd_val(pgd) & PAGE_MASK; } +extern pte_t (*mk_pte)(unsigned long, pgprot_t); +extern pte_t (*mk_pte_phys)(unsigned long, pgprot_t); +extern pte_t (*mk_pte_io)(unsigned long, pgprot_t, int); -extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep) -{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; } +extern void (*pgd_set)(pgd_t *, pmd_t *); -/* to find an entry in a page-table-directory */ -#define PAGE_DIR_OFFSET(tsk,address) \ -((((unsigned long)(address)) >> 22) + (pgd_t *) (tsk)->tss.cr3) +extern pte_t (*pte_modify)(pte_t, pgprot_t); /* to find an entry in a page-table-directory */ -extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address) -{ - return (pgd_t *) tsk->tss.cr3 + (address >> PGDIR_SHIFT); -} +extern pgd_t * (*pgd_offset)(struct mm_struct *, unsigned long); /* Find an entry in the second-level page table.. */ -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} +extern pmd_t * (*pmd_offset)(pgd_t *, unsigned long); /* Find an entry in the third-level page table.. */ -extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); -} - +extern pte_t * (*pte_offset)(pmd_t *, unsigned long); /* * Allocate and free page tables. The xxx_kernel() versions are * used to allocate a kernel page table - this turns on ASN bits * if any, and marks the page tables reserved. */ -extern inline void pte_free_kernel(pte_t * pte) -{ - mem_map[MAP_NR(pte)] = 1; - free_page((unsigned long) pte); -} +extern void (*pte_free_kernel)(pte_t *); -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page; - mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED; - return page + address; - } - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; -} +extern pte_t * (*pte_alloc_kernel)(pmd_t *, unsigned long); /* * allocating and freeing a pmd is trivial: the 1-entry pmd is * inside the pgd, so has no extra memory associated with it. */ -extern inline void pmd_free_kernel(pmd_t * pmd) -{ -} +extern void (*pmd_free_kernel)(pmd_t *); -extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) -{ - return (pmd_t *) pgd; -} +extern pmd_t * (*pmd_alloc_kernel)(pgd_t *, unsigned long); -extern inline void pte_free(pte_t * pte) -{ - free_page((unsigned long) pte); -} +extern void (*pte_free)(pte_t *); -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page; - return page + address; - } - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; -} +extern pte_t * (*pte_alloc)(pmd_t *, unsigned long); /* * allocating and freeing a pmd is trivial: the 1-entry pmd is * inside the pgd, so has no extra memory associated with it. */ -extern inline void pmd_free(pmd_t * pmd) -{ -} +extern void (*pmd_free)(pmd_t *); -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) -{ - return (pmd_t *) pgd; -} +extern pmd_t * (*pmd_alloc)(pgd_t *, unsigned long); + +extern void (*pgd_free)(pgd_t *); + +extern pgd_t * (*pgd_alloc)(void); + +/* Fine grained cache/tlb flushing. */ + +#ifdef __SMP__ +extern void (*local_flush_cache_all)(void); +extern void (*local_flush_cache_mm)(struct mm_struct *); +extern void (*local_flush_cache_range)(struct mm_struct *, unsigned long start, + unsigned long end); +extern void (*local_flush_cache_page)(struct vm_area_struct *, unsigned long address); + +extern void (*local_flush_tlb_all)(void); +extern void (*local_flush_tlb_mm)(struct mm_struct *); +extern void (*local_flush_tlb_range)(struct mm_struct *, unsigned long start, + unsigned long end); +extern void (*local_flush_tlb_page)(struct vm_area_struct *, unsigned long address); + +extern void (*local_flush_page_to_ram)(unsigned long address); -extern inline void pgd_free(pgd_t *pgd) +extern void smp_flush_cache_all(void); +extern void smp_flush_cache_mm(struct mm_struct *mm); +extern void smp_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end); +extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page); + +extern void smp_flush_tlb_all(void); +extern void smp_flush_tlb_mm(struct mm_struct *mm); +extern void smp_flush_tlb_range(struct mm_struct *mm, + unsigned long start, + unsigned long end); +extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page); +extern void smp_flush_page_to_ram(unsigned long page); +#endif + +extern void (*flush_cache_all)(void); +extern void (*flush_cache_mm)(struct mm_struct *); +extern void (*flush_cache_range)(struct mm_struct *, unsigned long start, + unsigned long end); +extern void (*flush_cache_page)(struct vm_area_struct *, unsigned long address); + +extern void (*flush_tlb_all)(void); +extern void (*flush_tlb_mm)(struct mm_struct *); +extern void (*flush_tlb_range)(struct mm_struct *, unsigned long start, unsigned long end); +extern void (*flush_tlb_page)(struct vm_area_struct *, unsigned long address); + +extern void (*flush_page_to_ram)(unsigned long page); + +/* The permissions for pgprot_val to make a page mapped on the obio space */ +extern unsigned int pg_iobits; + +/* MMU context switching. */ +extern void (*switch_to_context)(struct task_struct *tsk); + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ + +#if 0 /* XXX try this soon XXX */ +extern void (*set_pte)(struct vm_area_struct *vma, unsigned long address, + pte_t *pteptr, pte_t pteval); +#else +extern void (*set_pte)(pte_t *pteptr, pte_t pteval); +#endif + +extern char *(*mmu_info)(void); + +/* Fault handler stuff... */ +#define FAULT_CODE_PROT 0x1 +#define FAULT_CODE_WRITE 0x2 +#define FAULT_CODE_USER 0x4 +extern void (*update_mmu_cache)(struct vm_area_struct *vma, unsigned long address, pte_t pte); + +extern int invalid_segment; + +#define SWP_TYPE(entry) (((entry)>>2) & 0x7f) +#define SWP_OFFSET(entry) (((entry) >> 9) & 0x7ffff) +#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9)) + +struct ctx_list { + struct ctx_list *next; + struct ctx_list *prev; + unsigned int ctx_number; + struct mm_struct *ctx_mm; +}; + +extern struct ctx_list *ctx_list_pool; /* Dynamically allocated */ +extern struct ctx_list ctx_free; /* Head of free list */ +extern struct ctx_list ctx_used; /* Head of used contexts list */ + +#define NO_CONTEXT -1 + +extern __inline__ void remove_from_ctx_list(struct ctx_list *entry) { - free_page((unsigned long) pgd); + entry->next->prev = entry->prev; + entry->prev->next = entry->next; } -extern inline pgd_t *pgd_alloc(void) + +extern __inline__ void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry) { - return (pgd_t *) get_free_page(GFP_KERNEL); + entry->next = head; + (entry->prev = head->prev)->next = entry; + head->prev = entry; } - -extern pgd_t swapper_pg_dir[1024]; +#define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry) +#define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry) #endif /* !(_SPARC_PGTABLE_H) */ diff --git a/include/asm-sparc/pgtsrmmu.h b/include/asm-sparc/pgtsrmmu.h new file mode 100644 index 000000000..f8ca14944 --- /dev/null +++ b/include/asm-sparc/pgtsrmmu.h @@ -0,0 +1,268 @@ +/* $Id: pgtsrmmu.h,v 1.24 1996/10/07 03:03:06 davem Exp $ + * pgtsrmmu.h: SRMMU page table defines and code. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_PGTSRMMU_H +#define _SPARC_PGTSRMMU_H + +#include <linux/config.h> +#include <asm/page.h> + +#if CONFIG_AP1000 +#include <asm/ap1000/apreg.h> +#endif + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define SRMMU_PMD_SHIFT 18 +#define SRMMU_PMD_SIZE (1UL << SRMMU_PMD_SHIFT) +#define SRMMU_PMD_MASK (~(SRMMU_PMD_SIZE-1)) +#define SRMMU_PMD_ALIGN(addr) (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define SRMMU_PGDIR_SHIFT 24 +#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT) +#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1)) +#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK) + +#define SRMMU_PTRS_PER_PTE 64 +#define SRMMU_PTRS_PER_PMD 64 +#define SRMMU_PTRS_PER_PGD 256 + +#define SRMMU_PTE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ +#define SRMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ +#define SRMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */ + +#define SRMMU_VMALLOC_START (0xfe300000) + +/* Definition of the values in the ET field of PTD's and PTE's */ +#define SRMMU_ET_MASK 0x3 +#define SRMMU_ET_INVALID 0x0 +#define SRMMU_ET_PTD 0x1 +#define SRMMU_ET_PTE 0x2 +#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */ + +/* Physical page extraction from PTP's and PTE's. */ +#define SRMMU_CTX_PMASK 0xfffffff0 +#define SRMMU_PTD_PMASK 0xfffffff0 +#define SRMMU_PTE_PMASK 0xffffff00 + +/* The pte non-page bits. Some notes: + * 1) cache, dirty, valid, and ref are frobbable + * for both supervisor and user pages. + * 2) exec and write will only give the desired effect + * on user pages + * 3) use priv and priv_readonly for changing the + * characteristics of supervisor ptes + */ +#define SRMMU_CACHE 0x80 +#define SRMMU_DIRTY 0x40 +#define SRMMU_REF 0x20 +#define SRMMU_EXEC 0x08 +#define SRMMU_WRITE 0x04 +#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */ +#define SRMMU_PRIV 0x1c +#define SRMMU_PRIV_RDONLY 0x18 + +#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY) + +/* Some day I will implement true fine grained access bits for + * user pages because the SRMMU gives us the capabilities to + * enforce all the protection levels that vma's can have. + * XXX But for now... + */ +#define SRMMU_PAGE_NONE __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_PRIV | SRMMU_REF) +#define SRMMU_PAGE_SHARED __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_WRITE | SRMMU_REF) +#define SRMMU_PAGE_COPY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_REF) +#define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_REF) +#define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \ + SRMMU_DIRTY | SRMMU_REF) + +/* SRMMU Register addresses in ASI 0x4. These are valid for all + * current SRMMU implementations that exist. + */ +#define SRMMU_CTRL_REG 0x00000000 +#define SRMMU_CTXTBL_PTR 0x00000100 +#define SRMMU_CTX_REG 0x00000200 +#define SRMMU_FAULT_STATUS 0x00000300 +#define SRMMU_FAULT_ADDR 0x00000400 + +/* + * "normal" sun systems have their memory on bus 0. This means the top + * 4 bits of 36 bit physical addresses are 0. We use this define to + * determine if a piece of memory might be normal memory, or if its + * definately some sort of device memory. + * + * On the AP+ normal memory is on bus 8. Why? Ask Fujitsu :-) +*/ +#if CONFIG_AP1000 +#define MEM_BUS_SPACE 8 +#else +#define MEM_BUS_SPACE 0 +#endif + +/* Accessing the MMU control register. */ +extern __inline__ unsigned int srmmu_get_mmureg(void) +{ + unsigned int retval; + __asm__ __volatile__("lda [%%g0] %1, %0\n\t" : + "=r" (retval) : + "i" (ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ void srmmu_set_mmureg(unsigned long regval) +{ + __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : : + "r" (regval), "i" (ASI_M_MMUREGS) : "memory"); + +} + +extern __inline__ void srmmu_set_ctable_ptr(unsigned long paddr) +{ + paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); +#if MEM_BUS_SPACE + paddr |= (MEM_BUS_SPACE<<28); +#endif + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (paddr), "r" (SRMMU_CTXTBL_PTR), + "i" (ASI_M_MMUREGS) : + "memory"); +} + +extern __inline__ unsigned long srmmu_get_ctable_ptr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_CTXTBL_PTR), + "i" (ASI_M_MMUREGS)); + return (retval & SRMMU_CTX_PMASK) << 4; +} + +extern __inline__ void srmmu_set_context(int context) +{ + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (context), "r" (SRMMU_CTX_REG), + "i" (ASI_M_MMUREGS) : "memory"); +#if CONFIG_AP1000 + /* The AP1000+ message controller also needs to know + the current task's context. */ + MSC_OUT(MSC_PID, context); +#endif +} + +extern __inline__ int srmmu_get_context(void) +{ + register int retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_CTX_REG), + "i" (ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ unsigned int srmmu_get_fstatus(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ unsigned int srmmu_get_faddr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS)); + return retval; +} + +/* This is guaranteed on all SRMMU's. */ +extern __inline__ void srmmu_flush_whole_tlb(void) +{ +#if CONFIG_AP1000 + extern void mc_tlb_flush_all(void); + mc_tlb_flush_all(); +#endif + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (0x400), /* Flush entire TLB!! */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +/* These flush types are not available on all chips... */ +extern __inline__ void srmmu_flush_tlb_ctx(void) +{ +#if CONFIG_AP1000 + mc_tlb_flush_ctx(); +#endif + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (0x300), /* Flush TLB ctx.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +extern __inline__ void srmmu_flush_tlb_region(unsigned long addr) +{ +#if CONFIG_AP1000 + mc_tlb_flush_region(); +#endif + addr &= SRMMU_PGDIR_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (addr | 0x200), /* Flush TLB region.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + + +extern __inline__ void srmmu_flush_tlb_segment(unsigned long addr) +{ +#if CONFIG_AP1000 + mc_tlb_flush_segment(); +#endif + addr &= SRMMU_PMD_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (addr | 0x100), /* Flush TLB segment.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +extern __inline__ void srmmu_flush_tlb_page(unsigned long page) +{ +#if CONFIG_AP1000 + mc_tlb_flush_page(page); +#endif + page &= PAGE_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (page), /* Flush TLB page.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +extern __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr) +{ + unsigned long retval; + + vaddr &= PAGE_MASK; + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE)); + + return retval; +} + +extern unsigned long (*srmmu_read_physical)(unsigned long paddr); +extern void (*srmmu_write_physical)(unsigned long paddr, unsigned long word); + +#endif /* !(_SPARC_PGTSRMMU_H) */ diff --git a/include/asm-sparc/pgtsun4.h b/include/asm-sparc/pgtsun4.h new file mode 100644 index 000000000..4161526c0 --- /dev/null +++ b/include/asm-sparc/pgtsun4.h @@ -0,0 +1,10 @@ +/* $Id: pgtsun4.h,v 1.2 1995/11/25 02:32:26 davem Exp $ + * pgtsun4.c: Regular Sun4 MMU support goes in here. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_PGTSUN4_H +#define _SPARC_PGTSUN4_H + +#endif /* !(_SPARC_PGTSUN4_H) */ diff --git a/include/asm-sparc/pgtsun4c.h b/include/asm-sparc/pgtsun4c.h new file mode 100644 index 000000000..c54a6079d --- /dev/null +++ b/include/asm-sparc/pgtsun4c.h @@ -0,0 +1,151 @@ +/* $Id: pgtsun4c.h,v 1.27 1996/10/30 06:01:32 davem Exp $ + * pgtsun4c.h: Sun4c specific pgtable.h defines and code. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_PGTSUN4C_H +#define _SPARC_PGTSUN4C_H + +#include <asm/contregs.h> + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define SUN4C_PMD_SHIFT 22 +#define SUN4C_PMD_SIZE (1UL << SUN4C_PMD_SHIFT) +#define SUN4C_PMD_MASK (~(SUN4C_PMD_SIZE-1)) +#define SUN4C_PMD_ALIGN(addr) (((addr)+SUN4C_PMD_SIZE-1)&SUN4C_PMD_MASK) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define SUN4C_PGDIR_SHIFT 22 +#define SUN4C_PGDIR_SIZE (1UL << SUN4C_PGDIR_SHIFT) +#define SUN4C_PGDIR_MASK (~(SUN4C_PGDIR_SIZE-1)) +#define SUN4C_PGDIR_ALIGN(addr) (((addr)+SUN4C_PGDIR_SIZE-1)&SUN4C_PGDIR_MASK) + +/* To represent how the sun4c mmu really lays things out. */ +#define SUN4C_REAL_PGDIR_SHIFT 18 +#define SUN4C_REAL_PGDIR_SIZE (1UL << SUN4C_REAL_PGDIR_SHIFT) +#define SUN4C_REAL_PGDIR_MASK (~(SUN4C_REAL_PGDIR_SIZE-1)) +#define SUN4C_REAL_PGDIR_ALIGN(addr) (((addr)+SUN4C_REAL_PGDIR_SIZE-1)&SUN4C_REAL_PGDIR_MASK) + +/* + * To be efficient, and not have to worry about allocating such + * a huge pgd, we make the kernel sun4c tables each hold 1024 + * entries and the pgd similarly just like the i386 tables. + */ +#define SUN4C_PTRS_PER_PTE 1024 +#define SUN4C_PTRS_PER_PMD 1 +#define SUN4C_PTRS_PER_PGD 1024 + +/* On the sun4c the physical ram limit is 128MB. We set up our I/O + * translations at KERNBASE + 128MB for 1MB, then we begin the VMALLOC + * area, makes sense. This works out to the value below. + */ +#define SUN4C_VMALLOC_START (0xfe300000) + +/* + * Sparc SUN4C pte fields. + */ +#define _SUN4C_PAGE_VALID 0x80000000 /* valid page */ +#define _SUN4C_PAGE_WRITE 0x40000000 /* can be written to */ +#define _SUN4C_PAGE_PRIV 0x20000000 /* bit to signify privileged page */ +#define _SUN4C_PAGE_USER 0x00000000 /* User page */ +#define _SUN4C_PAGE_NOCACHE 0x10000000 /* non-cacheable page */ +#define _SUN4C_PAGE_IO 0x04000000 /* I/O page */ +#define _SUN4C_PAGE_REF 0x02000000 /* Page has been accessed/referenced */ +#define _SUN4C_PAGE_DIRTY 0x01000000 /* Page has been modified, is dirty */ +#define _SUN4C_PAGE_PRESENT 0x00400000 /* present (known) page */ + +#define _SUN4C_PAGE_CHG_MASK (0xffff | _SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY) + +#define SUN4C_PAGE_NONE __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_PRIV | \ + _SUN4C_PAGE_REF) +#define SUN4C_PAGE_SHARED __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | \ + _SUN4C_PAGE_USER | _SUN4C_PAGE_REF) +#define SUN4C_PAGE_COPY __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_USER | \ + _SUN4C_PAGE_REF) +#define SUN4C_PAGE_READONLY __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_USER | \ + _SUN4C_PAGE_REF) +#define SUN4C_PAGE_KERNEL __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | \ + _SUN4C_PAGE_PRIV | _SUN4C_PAGE_DIRTY | \ + _SUN4C_PAGE_REF | _SUN4C_PAGE_NOCACHE) + +extern __inline__ unsigned long sun4c_get_synchronous_error(void) +{ + unsigned long sync_err; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (sync_err) : + "r" (AC_SYNC_ERR), "i" (ASI_CONTROL)); + return sync_err; +} + +extern __inline__ unsigned long sun4c_get_synchronous_address(void) +{ + unsigned long sync_addr; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (sync_addr) : + "r" (AC_SYNC_VA), "i" (ASI_CONTROL)); + return sync_addr; +} + +/* SUN4C pte, segmap, and context manipulation */ +extern __inline__ unsigned long sun4c_get_segmap(unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" : + "=r" (entry) : + "r" (addr), "i" (ASI_SEGMAP)); + + return entry; +} + +extern __inline__ void sun4c_put_segmap(unsigned long addr, unsigned long entry) +{ + + __asm__ __volatile__("\n\tstba %1, [%0] %2\n\t" : : + "r" (addr), "r" (entry), + "i" (ASI_SEGMAP)); + + return; +} + +extern __inline__ unsigned long sun4c_get_pte(unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : + "=r" (entry) : + "r" (addr), "i" (ASI_PTE)); + return entry; +} + +extern __inline__ void sun4c_put_pte(unsigned long addr, unsigned long entry) +{ + __asm__ __volatile__("\n\tsta %1, [%0] %2\n\t" : : + "r" (addr), + "r" (entry), "i" (ASI_PTE)); + + return; +} + +extern __inline__ int sun4c_get_context(void) +{ + register int ctx; + + __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" : + "=r" (ctx) : + "r" (AC_CONTEXT), "i" (ASI_CONTROL)); + + return ctx; +} + +extern __inline__ int sun4c_set_context(int ctx) +{ + __asm__ __volatile__("\n\tstba %0, [%1] %2\n\t" : : + "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL)); + + return ctx; +} + +#endif /* !(_SPARC_PGTSUN4C_H) */ diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h new file mode 100644 index 000000000..1df2f62d2 --- /dev/null +++ b/include/asm-sparc/posix_types.h @@ -0,0 +1,111 @@ +#ifndef __ARCH_SPARC_POSIX_TYPES_H +#define __ARCH_SPARC_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +/* When cross-compilation is no longer an issue, fix this. */ +#if defined(__svr4__) || defined(__ELF__) +typedef unsigned int __kernel_size_t; +#else +typedef long unsigned int __kernel_size_t; +#endif /* !(__svr4__ || __ELF__) */ + +typedef int __kernel_ssize_t; +typedef long int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef short __kernel_nlink_t; +typedef long __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL<<_rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant cases (8 or 32 longs, + * for 256 and 1024-bit fd_sets respectively) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *p) +{ + unsigned long *tmp = p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 32: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0; + tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0; + tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0; + tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0; + return; + case 16: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + return; + case 8: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + return; + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */ diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index 7e18bfb2f..dd5a0dfcf 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -1,4 +1,5 @@ -/* include/asm-sparc/processor.h +/* $Id: processor.h,v 1.48 1996/10/27 08:55:36 davem Exp $ + * include/asm-sparc/processor.h * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) */ @@ -6,151 +7,159 @@ #ifndef __ASM_SPARC_PROCESSOR_H #define __ASM_SPARC_PROCESSOR_H +#include <linux/a.out.h> + +#include <asm/psr.h> +#include <asm/ptrace.h> +#include <asm/head.h> +#include <asm/signal.h> +#include <asm/segment.h> + /* * Bus types */ -#define EISA_bus 1 +#define EISA_bus 0 #define EISA_bus__is_a_macro /* for versions in ksyms.c */ #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ /* - * Write Protection works right in supervisor mode on the Sparc + * The sparc has no problems with write protection */ - #define wp_works_ok 1 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */ -/* - * User space process size: 3GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. - * - * "this is gonna have to change to 1gig for the sparc" - David S. Miller - */ -#define TASK_SIZE (0xC0000000UL) +/* Whee, this is STACK_TOP and the lowest kernel address too... */ +#define TASK_SIZE (page_offset) -/* - * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. - */ -#define IO_BITMAP_SIZE 32 - -/* The first five entries here MUST be the first four. This allows me to - * do %lo(offset) loads and stores in entry.S. See TRAP_WIN_CLEAN to see - * why. - */ +/* Ok this is hot. Sparc exception save area. */ +struct exception_struct { + unsigned long count; /* Exception count */ + unsigned long pc; /* Callers PC for copy/clear user */ + unsigned long expc; /* Where to jump when exception signaled */ + unsigned long address; /* Saved user base address for transfer */ +}; +/* The Sparc processor specific thread struct. */ struct thread_struct { - unsigned long uwindows; /* how many user windows are in the set */ - unsigned long wim; /* user's window invalid mask */ - unsigned long w_saved; /* how many windows saved in reg_window[] */ - unsigned long ksp; /* kernel stack pointer */ - unsigned long usp; /* user's sp, throw reg windows here */ - unsigned long psr; /* save for condition codes */ - unsigned long reg_window[16*24]; - unsigned long cr3; /* why changed from ptbr? */ - unsigned int pcc; - unsigned int asn; - unsigned long unique; + unsigned long uwinmask __attribute__ ((aligned (8))); + struct pt_regs *kregs; + + /* For signal handling */ + unsigned long sig_address __attribute__ ((aligned (8))); + unsigned long sig_desc; + + /* Context switch saved kernel state. */ + unsigned long ksp __attribute__ ((aligned (8))); + unsigned long kpc; + unsigned long kpsr; + unsigned long kwim; + + /* Special child fork kpsr/kwim values. */ + unsigned long fork_kpsr __attribute__ ((aligned (8))); + unsigned long fork_kwim; + + /* A place to store user windows and stack pointers + * when the stack needs inspection. + */ +#define NSWINS 8 + struct reg_window reg_window[NSWINS] __attribute__ ((aligned (8))); + unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8))); + unsigned long w_saved; + + /* Floating point regs */ + unsigned long float_regs[64] __attribute__ ((aligned (8))); + unsigned long fsr; + unsigned long fpqdepth; + struct fpq { + unsigned long *insn_addr; + unsigned long insn; + } fpqueue[16]; + struct sigstack sstk_info; unsigned long flags; - unsigned long res1, res2; - unsigned long pc; /* program counter */ - unsigned long npc; /* next program counter */ - -/* 8 local registers + 8 in registers * 24 register windows. - * Most sparcs I know of only have 8 windows implemented, - * we determine how many at boot time and store that value - * in nwindows. - */ - unsigned long globl_regs[8]; /* global regs need to be saved too */ - unsigned long yreg; - unsigned long float_regs[64]; /* V8 and below have 32, V9 has 64 */ + struct exception_struct ex __attribute__ ((aligned (8))); + int current_ds; + struct exec core_exec; /* just what it says. */ }; -#define INIT_MMAP { &init_task, 0x0, 0x40000000, \ - PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC } +#define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */ +#define SPARC_FLAG_UNALIGNED 0x2 /* is allowed to do unaligned accesses */ + +#define INIT_MMAP { &init_mm, (0), (0), \ + __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC } #define INIT_TSS { \ - 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, }, \ +/* uwinmask, kregs, sig_address, sig_desc, ksp, kpc, kpsr, kwim */ \ + 0, 0, 0, 0, 0, 0, 0, 0, \ +/* fork_kpsr, fork_kwim */ \ + 0, 0, \ +/* reg_window */ \ +{ { { 0, }, { 0, } }, }, \ +/* rwbuf_stkptrs */ \ +{ 0, 0, 0, 0, 0, 0, 0, 0, }, \ +/* w_saved */ \ + 0, \ +/* FPU regs */ { 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, 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, 0, 0, 0, 0, 0, 0, }, \ +/* FPU status, FPU qdepth, FPU queue */ \ + 0, 0, { { 0, 0, }, }, \ +/* sstk_info */ \ +{ 0, 0, }, \ +/* flags, ex, current_ds, */ \ + SPARC_FLAG_KTHREAD, { 0, }, USER_DS, \ +/* core_exec */ \ +{ 0, }, \ } -/* The thread_frame is what needs to be set up in certain circumstances - * upon entry to a trap. It is also loaded sometimes during a window - * spill if things don't go right (bad user stack pointer). In reality - * it is not per-process per se, it just sits in the kernel stack while - * the current process is in a handler then it is basically forgotten - * about. - */ - -struct thread_frame { - unsigned int thr_psr; - unsigned int thr_pc; - unsigned int thr_npc; - unsigned int thr_y; - unsigned int thr_globals[8]; - unsigned int thr_outs[8]; -}; - -/* - * These are the "cli()" and "sti()" for software interrupts - * They work by increasing/decreasing the "intr_count" value, - * and as such can be nested arbitrarily. - */ -extern inline void start_bh_atomic(void) +/* Return saved PC of a blocked thread. */ +extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t) { - unsigned long dummy, psr; - __asm__ __volatile__("rd %%psr, %2\n\t" - "wr %2, 0x20, %%psr\n\t" /* disable traps */ - "ld %1,%0\n\t" - "add %0,1,%0\n\t" - "st %0,%1\n\t" - "wr %2, 0x0, %%psr\n\t" /* enable traps */ - : "=r" (dummy), "=m" (intr_count) - : "0" (0), "r" (psr=0)); + return t->kpc; } -extern inline void end_bh_atomic(void) +/* Do necessary setup to start up a newly executed thread. */ +extern __inline__ void start_thread(struct pt_regs * regs, unsigned long pc, + unsigned long sp) { - unsigned long dummy, psr; - __asm__ __volatile__("rd %%psr, %2\n\t" - "wr %2, 0x20, %%psr\n\t" - "ld %1,%0\n\t" - "sub %0,1,%0\n\t" - "st %0,%1\n\t" - "wr %2, 0x0, %%psr\n\t" - : "=r" (dummy), "=m" (intr_count) - : "0" (0), "r" (psr=0)); + register unsigned long zero asm("g1"); + + regs->psr = (regs->psr & (PSR_CWP)) | PSR_S; + regs->pc = ((pc & (~3)) - 4); + regs->npc = regs->pc + 4; + regs->y = 0; + zero = 0; + __asm__ __volatile__("std\t%%g0, [%0 + %3 + 0x00]\n\t" + "std\t%%g0, [%0 + %3 + 0x08]\n\t" + "std\t%%g0, [%0 + %3 + 0x10]\n\t" + "std\t%%g0, [%0 + %3 + 0x18]\n\t" + "std\t%%g0, [%0 + %3 + 0x20]\n\t" + "std\t%%g0, [%0 + %3 + 0x28]\n\t" + "std\t%%g0, [%0 + %3 + 0x30]\n\t" + "st\t%1, [%0 + %3 + 0x38]\n\t" + "st\t%%g0, [%0 + %3 + 0x3c]" + : : "r" (regs), "r" (sp - REGWIN_SZ), "r" (zero), + "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); } -#endif /* __ASM_SPARC_PROCESSOR_H */ +#define release_thread(tsk) do { } while(0) + +#ifdef __KERNEL__ +extern unsigned long (*alloc_kernel_stack)(struct task_struct *tsk); +extern void (*free_kernel_stack)(unsigned long stack); +extern struct task_struct *(*alloc_task_struct)(void); +extern void (*free_task_struct)(struct task_struct *tsk); +#endif + +/* + * Return_address is a replacement for __builtin_return_address(count) + * which on certain architectures cannot reasonably be implemented in GCC + * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * Note that __builtin_return_address(x>=1) is forbidden because the GCC + * aborts compilation on some CPUs. It's simply not possible to unwind + * some CPU's stackframes. + */ +#define return_address() __builtin_return_address(0) +#endif /* __ASM_SPARC_PROCESSOR_H */ diff --git a/include/asm-sparc/psr.h b/include/asm-sparc/psr.h index 60b9757ad..829ca47b6 100644 --- a/include/asm-sparc/psr.h +++ b/include/asm-sparc/psr.h @@ -1,36 +1,23 @@ -/* psr.h: This file holds the macros for masking off various parts of - the processor status register on the Sparc. This is valid - for Version 8. On the V9 this is renamed to the PSTATE - register and its members are accessed as fields like - PSTATE.PRIV for the current CPU privilege level. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ +/* $Id: psr.h,v 1.12 1996/09/30 02:23:19 davem Exp $ + * psr.h: This file holds the macros for masking off various parts of + * the processor status register on the Sparc. This is valid + * for Version 8. On the V9 this is renamed to the PSTATE + * register and its members are accessed as fields like + * PSTATE.PRIV for the current CPU privilege level. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ #ifndef __LINUX_SPARC_PSR_H #define __LINUX_SPARC_PSR_H -#define __LINUX_SPARC_V8 /* duh */ - -#ifdef __LINUX_SPARC_V8 - /* The Sparc PSR fields are laid out as the following: - - ------------------------------------------------------------------------ - | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP | -bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | - ------------------------------------------------------------------------ - - The PSR can only be directly be written/read by the privileged instructions - 'rd' and 'wr'. Certain fields are changed as a side effect due to the 'Ticc', - 'save', 'restore', and 'rett' instructions. Also the integer condition codes - 'icc' are modified by various arithmetic instructions. - - For example: wr %o2, or'd_bit_pattern, %psr - rd %psr, %o3 - -*/ - + * + * ------------------------------------------------------------------------ + * | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP | + * | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | + * ------------------------------------------------------------------------ + */ #define PSR_CWP 0x0000001f /* current window pointer */ #define PSR_ET 0x00000020 /* enable traps field */ #define PSR_PS 0x00000040 /* previous privilege level */ @@ -38,6 +25,7 @@ bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | #define PSR_PIL 0x00000f00 /* processor interrupt level */ #define PSR_EF 0x00001000 /* enable floating point */ #define PSR_EC 0x00002000 /* enable co-processor */ +#define PSR_LE 0x00008000 /* SuperSparcII little-endian */ #define PSR_ICC 0x00f00000 /* integer condition codes */ #define PSR_C 0x00100000 /* carry bit */ #define PSR_V 0x00200000 /* overflow bit */ @@ -46,54 +34,45 @@ bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | #define PSR_VERS 0x0f000000 /* cpu-version field */ #define PSR_IMPL 0xf0000000 /* cpu-implementation field */ -#endif /* !(__LINUX_SPARC_V8) */ - -#ifdef __LINUX_SPARC_V9 - -/* The information available in the %psr on the V8 is spread amongst - a whole bunch of registers on the V9. The main one being PSTATE. - - -------------------------------------------------------- - | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG | -bits | 9 | 8 | 7-6 | 5 | 4 | 3 | 2 | 1 | 0 | - -------------------------------------------------------- - - Writes and reads to PSTATE are done via 'wrpr' and 'rdpr' instructions. - - For example: wrpr %o2, or'd_bit_pattern, %pstate - rdpr %pstate, %o3 -*/ - -#define PSTATE_AG 0x001 /* Alternate Globals */ -#define PSTATE_IE 0x002 /* Interrupt Enable */ -#define PSTATE_PRIV 0x004 /* Current privilege level */ -#define PSTATE_AM 0x008 /* Address mask (data reads can */ - /* be chosen to be either big or */ - /* little endian on V9). */ -#define PSTATE_PEF 0x010 /* enable floating point */ -#define PSTATE_RED 0x020 /* RED trap state (set if trap */ - /* trap_level == max_tl). */ -#define PSTATE_MM 0x0c0 /* Memory model (Total Store */ - /* Order=0, Partial Store Order */ - /* =1 or Relaxed Memory Order=2) */ -#define PSTATE_TLE 0x100 /* Trap Little Endian */ -#define PSTATE_CLE 0x200 /* Current Little Endian */ - - -/* The Version Register holds vendor information for the chip: - - --------------------------------------------------------------------------- - | manufacturer | implementation | mask | reserved | maxtl | resv | maxwin | -bits| 63-48 | 47-32 | 31-24| 23-16 | 15-8 | 7-5 | 4-0 | - --------------------------------------------------------------------------- - -*/ - -#define VERS_MAXWIN 0x000000000000001f /* 'nwindows' on this chip */ -#define VERS_MAXTL 0x00000000000ff000 /* Maximum Trap-level supported */ -#define VERS_MASK 0x0000000ff0000000 /* impl. dep. chip mask revision */ -#define VERS_MANUF 0xffff000000000000 /* Manufacturer ID code */ - -#endif /* !(__LINUX_SPARC_V9) */ +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ +/* Get the %psr register. */ +extern __inline__ unsigned int get_psr(void) +{ + unsigned int psr; + __asm__ __volatile__("rd\t%%psr, %0" : + "=r" (psr)); + return psr; +} + +extern __inline__ void put_psr(unsigned int new_psr) +{ + __asm__ __volatile__("wr\t%0, 0x0, %%psr\n\t" + "nop; nop; nop;" : : + "r" (new_psr)); +} + +/* Get the %fsr register. Be careful, make sure the floating point + * enable bit is set in the %psr when you execute this or you will + * incur a trap. + */ + +extern unsigned int fsr_storage; + +extern __inline__ unsigned int get_fsr(void) +{ + unsigned int fsr = 0; + + __asm__ __volatile__("st\t%%fsr, %1\n\t" + "ld\t%1, %0" : + "=r" (fsr) : + "m" (fsr_storage)); + return fsr; +} + +#endif /* !(__ASSEMBLY__) */ + +#endif /* (__KERNEL__) */ #endif /* !(__LINUX_SPARC_PSR_H) */ diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index 70fb8d5df..d357ab034 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -1,32 +1,195 @@ +/* $Id: ptrace.h,v 1.22 1996/10/27 08:55:38 davem Exp $ */ #ifndef _SPARC_PTRACE_H #define _SPARC_PTRACE_H -/* I have not looked enough into how this should be done. Without playing - * lots of tricks to optimize I think we need to save the whole register - * window frame plus the floating-point registers. We'll see... +#include <asm/psr.h> + +/* This struct defines the way the registers are stored on the + * stack during a system call and basically all traps. */ -/* this struct defines the way the registers are stored on the - stack during a system call. */ +#ifndef __ASSEMBLY__ struct pt_regs { - unsigned long ps; /* previous supervisor, same as alpha I believe */ - unsigned long pc; /* current and next program counter */ + unsigned long psr; + unsigned long pc; unsigned long npc; - unsigned long sp; /* stack and frame pointer */ - unsigned long fp; - unsigned long psr; /* for condition codes */ - unsigned long nuwin; /* number of user windows */ - /* not sure yet whether all regs are necessary - * but this is how it is traditionally done on the sparc. - */ - unsigned long u_regs[24*16]; - unsigned long f_regs[64]; /* yuck yuck yuck */ + unsigned long y; + unsigned long u_regs[16]; /* globals and ins */ +}; + +#define UREG_G0 0 +#define UREG_G1 1 +#define UREG_G2 2 +#define UREG_G3 3 +#define UREG_G4 4 +#define UREG_G5 5 +#define UREG_G6 6 +#define UREG_G7 7 +#define UREG_I0 8 +#define UREG_I1 9 +#define UREG_I2 10 +#define UREG_I3 11 +#define UREG_I4 12 +#define UREG_I5 13 +#define UREG_I6 14 +#define UREG_I7 15 +#define UREG_WIM UREG_G0 +#define UREG_FADDR UREG_G0 +#define UREG_FP UREG_I6 +#define UREG_RETPC UREG_I7 + +/* A register window */ +struct reg_window { + unsigned long locals[8]; + unsigned long ins[8]; }; +/* A Sparc stack frame */ +struct sparc_stackf { + unsigned long locals[8]; + unsigned long ins[6]; + struct sparc_stackf *fp; + unsigned long callers_pc; + char *structptr; + unsigned long xargs[6]; + unsigned long xxargs[1]; +}; + +#define TRACEREG_SZ sizeof(struct pt_regs) +#define STACKFRAME_SZ sizeof(struct sparc_stackf) +#define REGWIN_SZ sizeof(struct reg_window) + #ifdef __KERNEL__ -#define user_mode(regs) (0x0) /* if previous supervisor is 0, came from user */ +#define user_mode(regs) (!((regs)->psr & PSR_PS)) +#define instruction_pointer(regs) ((regs)->pc) extern void show_regs(struct pt_regs *); #endif +#else /* __ASSEMBLY__ */ +/* For assembly code. */ +#define TRACEREG_SZ 0x50 +#define STACKFRAME_SZ 0x60 +#define REGWIN_SZ 0x40 #endif + +/* First generic task_struct offsets. sizeof(task_struct)=1616 */ +#define TASK_STATE 0x000 +#define TASK_PRIORITY 0x008 +#define TASK_SIGNAL 0x00c +#define TASK_BLOCKED 0x010 +#define TASK_FLAGS 0x014 +#define TASK_SAVED_KSTACK 0x054 +#define TASK_KSTACK_PG 0x058 + +/* Thread stuff. */ +#define THREAD_UMASK 0x210 +#define THREAD_SADDR 0x218 +#define THREAD_SDESC 0x21c +#define THREAD_KSP 0x220 +#define THREAD_KPC 0x224 +#define THREAD_KPSR 0x228 +#define THREAD_KWIM 0x22c +#define THREAD_FORK_KPSR 0x230 +#define THREAD_FORK_KWIM 0x234 +#define THREAD_REG_WINDOW 0x238 +#define THREAD_STACK_PTRS 0x438 +#define THREAD_W_SAVED 0x458 +#define THREAD_FLOAT_REGS 0x460 +#define THREAD_FSR 0x560 +#define THREAD_SIGSTK 0x5e8 +#define THREAD_FLAGS 0x5f0 +#define THREAD_EX_COUNT 0x5f8 +#define THREAD_EX_PC 0x5fc +#define THREAD_EX_EXPC 0x600 +#define THREAD_EX_ADDR 0x604 +#define THREAD_DS 0x608 +#define THREAD_MM 0x638 +#define THREAD_MM_CTX 0x008 + +/* These are for pt_regs. */ +#define PT_PSR 0x0 +#define PT_PC 0x4 +#define PT_NPC 0x8 +#define PT_Y 0xc +#define PT_G0 0x10 +#define PT_WIM PT_G0 +#define PT_G1 0x14 +#define PT_G2 0x18 +#define PT_G3 0x1c +#define PT_G4 0x20 +#define PT_G5 0x24 +#define PT_G6 0x28 +#define PT_G7 0x2c +#define PT_I0 0x30 +#define PT_I1 0x34 +#define PT_I2 0x38 +#define PT_I3 0x3c +#define PT_I4 0x40 +#define PT_I5 0x44 +#define PT_I6 0x48 +#define PT_FP PT_I6 +#define PT_I7 0x4c + +/* Reg_window offsets */ +#define RW_L0 0x00 +#define RW_L1 0x04 +#define RW_L2 0x08 +#define RW_L3 0x0c +#define RW_L4 0x10 +#define RW_L5 0x14 +#define RW_L6 0x18 +#define RW_L7 0x1c +#define RW_I0 0x20 +#define RW_I1 0x24 +#define RW_I2 0x28 +#define RW_I3 0x2c +#define RW_I4 0x30 +#define RW_I5 0x34 +#define RW_I6 0x38 +#define RW_I7 0x3c + +/* Stack_frame offsets */ +#define SF_L0 0x00 +#define SF_L1 0x04 +#define SF_L2 0x08 +#define SF_L3 0x0c +#define SF_L4 0x10 +#define SF_L5 0x14 +#define SF_L6 0x18 +#define SF_L7 0x1c +#define SF_I0 0x20 +#define SF_I1 0x24 +#define SF_I2 0x28 +#define SF_I3 0x2c +#define SF_I4 0x30 +#define SF_I5 0x34 +#define SF_FP 0x38 +#define SF_PC 0x3c +#define SF_RETP 0x40 +#define SF_XARG0 0x44 +#define SF_XARG1 0x48 +#define SF_XARG2 0x4c +#define SF_XARG3 0x50 +#define SF_XARG4 0x54 +#define SF_XARG5 0x58 +#define SF_XXARG 0x5c + +/* Stuff for the ptrace system call */ +#define PTRACE_SUNATTACH 10 +#define PTRACE_SUNDETACH 11 +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 +#define PTRACE_READDATA 16 +#define PTRACE_WRITEDATA 17 +#define PTRACE_READTEXT 18 +#define PTRACE_WRITETEXT 19 +#define PTRACE_GETFPAREGS 20 +#define PTRACE_SETFPAREGS 21 + +#define PTRACE_GETUCODE 29 /* stupid bsd-ism */ + + +#endif /* !(_SPARC_PTRACE_H) */ diff --git a/include/asm-sparc/reg.h b/include/asm-sparc/reg.h new file mode 100644 index 000000000..ed60ebec5 --- /dev/null +++ b/include/asm-sparc/reg.h @@ -0,0 +1,79 @@ +/* + * linux/asm-sparc/reg.h + * Layout of the registers as expected by gdb on the Sparc + * we should replace the user.h definitions with those in + * this file, we don't even use the other + * -miguel + * + * The names of the structures, constants and aliases in this file + * have the same names as the sunos ones, some programs rely on these + * names (gdb for example). + * + */ + +#ifndef __SPARC_REG_H +#define __SPARC_REG_H + +struct regs { + int r_psr; +#define r_ps r_psr + int r_pc; + int r_npc; + int r_y; + int r_g1; + int r_g2; + int r_g3; + int r_g4; + int r_g5; + int r_g6; + int r_g7; + int r_o0; + int r_o1; + int r_o2; + int r_o3; + int r_o4; + int r_o5; + int r_o6; + int r_o7; +}; + +struct fpq { + unsigned long *addr; + unsigned long instr; +}; + +struct fq { + union { + double whole; + struct fpq fpq; + } FQu; +}; + +#define FPU_REGS_TYPE unsigned int +#define FPU_FSR_TYPE unsigned + +struct fp_status { + union { + FPU_REGS_TYPE Fpu_regs[32]; + double Fpu_dregs[16]; + } fpu_fr; + FPU_FSR_TYPE Fpu_fsr; + unsigned Fpu_flags; + unsigned Fpu_extra; + unsigned Fpu_qcnt; + struct fq Fpu_q[16]; +}; + +#define fpu_regs f_fpstatus.fpu_fr.Fpu_regs +#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs +#define fpu_fsr f_fpstatus.Fpu_fsr +#define fpu_flags f_fpstatus.Fpu_flags +#define fpu_extra f_fpstatus.Fpu_extra +#define fpu_q f_fpstatus.Fpu_q +#define fpu_qcnt f_fpstatus.Fpu_qcnt + +struct fpu { + struct fp_status f_fpstatus; +}; + +#endif /* __SPARC_REG_H */ diff --git a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h new file mode 100644 index 000000000..61a137b48 --- /dev/null +++ b/include/asm-sparc/resource.h @@ -0,0 +1,38 @@ +/* $Id: resource.h,v 1.5 1995/11/25 02:32:35 davem Exp $ + * resource.h: Resource definitions. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_RESOURCE_H +#define _SPARC_RESOURCE_H + +/* + * Resource limits + */ + +#define RLIMIT_CPU 0 /* CPU time in ms */ +#define RLIMIT_FSIZE 1 /* Maximum filesize */ +#define RLIMIT_DATA 2 /* max data size */ +#define RLIMIT_STACK 3 /* max stack size */ +#define RLIMIT_CORE 4 /* max core file size */ +#define RLIMIT_RSS 5 /* max resident set size */ +#define RLIMIT_NOFILE 6 /* max number of open files */ +#define RLIMIT_NPROC 7 /* max number of processes */ +#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ +#define RLIM_NLIMITS 9 + +#ifdef __KERNEL__ + +#define INIT_RLIMITS \ +{ \ + {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \ + {LONG_MAX, LONG_MAX}, {_STK_LIM, _STK_LIM}, \ + { 0, LONG_MAX}, {LONG_MAX, LONG_MAX}, \ + {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER}, {NR_OPEN, NR_OPEN}, \ + {LONG_MAX, LONG_MAX}, \ +} + +#endif /* __KERNEL__ */ + +#endif /* !(_SPARC_RESOURCE_H) */ diff --git a/include/asm-sparc/ross.h b/include/asm-sparc/ross.h new file mode 100644 index 000000000..e6b0ddc26 --- /dev/null +++ b/include/asm-sparc/ross.h @@ -0,0 +1,174 @@ +/* $Id: ross.h,v 1.11 1996/08/29 09:48:40 davem Exp $ + * ross.h: Ross module specific definitions and defines. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_ROSS_H +#define _SPARC_ROSS_H + +#include <asm/asi.h> + +/* Ross made Hypersparcs have a %psr 'impl' field of '0001'. The 'vers' + * field has '1111'. + */ + +/* The MMU control register fields on the HyperSparc. + * + * ----------------------------------------------------------------- + * |implvers| RSV |CWR|SE|WBE| MID |BM| C|CS|MR|CM|RSV|CE|RSV|NF|ME| + * ----------------------------------------------------------------- + * 31 24 23-22 21 20 19 18-15 14 13 12 11 10 9 8 7-2 1 0 + * + * Phew, lots of fields there ;-) + * + * CWR: Cache Wrapping Enabled, if one cache wrapping is on. + * SE: Snoop Enable, turns on bus snooping for cache activity if one. + * WBE: Write Buffer Enable, one turns it on. + * MID: The ModuleID of the chip for MBus transactions. + * BM: Boot-Mode. One indicates the MMU is in boot mode. + * C: Indicates whether accesses are cachable while the MMU is + * disabled. + * CS: Cache Size -- 0 = 128k, 1 = 256k + * MR: Memory Reflection, one indicates that the memory bus connected + * to the MBus supports memory reflection. + * CM: Cache Mode -- 0 = write-through, 1 = copy-back + * CE: Cache Enable -- 0 = no caching, 1 = cache is on + * NF: No Fault -- 0 = faults trap the CPU from supervisor mode + * 1 = faults from supervisor mode do not generate traps + * ME: MMU Enable -- 0 = MMU is off, 1 = MMU is on + */ + +#define HYPERSPARC_CWENABLE 0x00200000 +#define HYPERSPARC_SBENABLE 0x00100000 +#define HYPERSPARC_WBENABLE 0x00080000 +#define HYPERSPARC_MIDMASK 0x00078000 +#define HYPERSPARC_BMODE 0x00004000 +#define HYPERSPARC_ACENABLE 0x00002000 +#define HYPERSPARC_CSIZE 0x00001000 +#define HYPERSPARC_MRFLCT 0x00000800 +#define HYPERSPARC_CMODE 0x00000400 +#define HYPERSPARC_CENABLE 0x00000100 +#define HYPERSPARC_NFAULT 0x00000002 +#define HYPERSPARC_MENABLE 0x00000001 + + +/* The ICCR instruction cache register on the HyperSparc. + * + * ----------------------------------------------- + * | | FTD | ICE | + * ----------------------------------------------- + * 31 1 0 + * + * This register is accessed using the V8 'wrasr' and 'rdasr' + * opcodes, since not all assemblers understand them and those + * that do use different semantics I will just hard code the + * instruction with a '.word' statement. + * + * FTD: If set to one flush instructions executed during an + * instruction cache hit occurs, the corresponding line + * for said cache-hit is invalidated. If FTD is zero, + * an unimplemented 'flush' trap will occur when any + * flush is executed by the processor. + * + * ICE: If set to one, the instruction cache is enabled. If + * zero, the cache will not be used for instruction fetches. + * + * All other bits are read as zeros, and writes to them have no + * effect. + * + * Wheee, not many assemblers understand the %iccr register nor + * the generic asr r/w instructions. + * + * 1000 0011 0100 0111 1100 0000 0000 0000 ! rd %iccr, %g1 + * + * 0x 8 3 4 7 c 0 0 0 ! 0x8347c000 + * + * 1011 1111 1000 0000 0110 0000 0000 0000 ! wr %g1, 0x0, %iccr + * + * 0x b f 8 0 6 0 0 0 ! 0xbf806000 + * + */ + +#define HYPERSPARC_ICCR_FTD 0x00000002 +#define HYPERSPARC_ICCR_ICE 0x00000001 + +extern __inline__ unsigned int get_ross_icr(void) +{ + unsigned int icreg; + + __asm__ __volatile__(".word 0x8347c000\n\t" /* rd %iccr, %g1 */ + "mov %%g1, %0\n\t" : + "=r" (icreg) : : + "g1", "memory"); + + return icreg; +} + +extern __inline__ void put_ross_icr(unsigned int icreg) +{ + __asm__ __volatile__("or %%g0, %0, %%g1\n\t" + ".word 0xbf806000\n\t" /* wr %g1, 0x0, %iccr */ + "nop\n\t" + "nop\n\t" + "nop\n\t" : : + "r" (icreg) : + "g1", "memory"); + + return; +} + +/* HyperSparc specific cache flushing. */ + +/* This is for the on-chip instruction cache. */ +extern __inline__ void hyper_flush_whole_icache(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_FLUSH_IWHOLE)); + return; +} + +extern int vac_cache_size; +extern int vac_line_size; + +extern __inline__ void hyper_clear_all_tags(void) +{ + unsigned long addr; + + for(addr = 0; addr < vac_cache_size; addr += vac_line_size) + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_DATAC_TAG)); +} + +extern __inline__ void hyper_flush_unconditional_combined(void) +{ + unsigned long addr; + + for(addr = 0; addr < vac_cache_size; addr += vac_line_size) + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_CTX)); +} + +extern __inline__ void hyper_flush_cache_user(void) +{ + unsigned long addr; + + for(addr = 0; addr < vac_cache_size; addr += vac_line_size) + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_USER)); +} + +extern __inline__ void hyper_flush_cache_page(unsigned long page) +{ + unsigned long end; + + page &= PAGE_MASK; + end = page + PAGE_SIZE; + while(page < end) { + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (page), "i" (ASI_M_FLUSH_PAGE)); + page += vac_line_size; + } +} + +#endif /* !(_SPARC_ROSS_H) */ diff --git a/include/asm-sparc/rtc.h b/include/asm-sparc/rtc.h new file mode 100644 index 000000000..f4f261dde --- /dev/null +++ b/include/asm-sparc/rtc.h @@ -0,0 +1,27 @@ +/* $Id: rtc.h,v 1.2 1996/08/21 23:17:39 ecd Exp $ + * + * rtc.h: Definitions for access to the Mostek real time clock + * + * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) + */ + +#ifndef _RTC_H +#define _RTC_H + +#include <linux/ioctl.h> + +struct rtc_time +{ + int sec; /* Seconds (0-59) */ + int min; /* Minutes (0-59) */ + int hour; /* Hour (0-23) */ + int dow; /* Day of the week (1-7) */ + int dom; /* Day of the month (1-31) */ + int month; /* Month of year (1-12) */ + int year; /* Year (0-99) */ +}; + +#define RTCGET _IOR('p', 20, struct rtc_time) +#define RTCSET _IOW('p', 21, struct rtc_time) + +#endif diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h new file mode 100644 index 000000000..cc9e75ae6 --- /dev/null +++ b/include/asm-sparc/sbus.h @@ -0,0 +1,101 @@ +/* $Id: sbus.h,v 1.11 1996/10/31 06:29:12 davem Exp $ + * sbus.h: Defines for the Sun SBus. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_SBUS_H +#define _SPARC_SBUS_H + +#include <asm/oplib.h> +#include <asm/iommu.h> + +/* We scan which devices are on the SBus using the PROM node device + * tree. SBus devices are described in two different ways. You can + * either get an absolute address at which to access the device, or + * you can get a SBus 'slot' number and an offset within that slot. + */ + +/* The base address at which to calculate device OBIO addresses. */ +#define SUN_SBUS_BVADDR 0xf8000000 +#define SBUS_OFF_MASK 0x01ffffff + +/* These routines are used to calculate device address from slot + * numbers + offsets, and vice versa. + */ + +extern __inline__ unsigned long sbus_devaddr(int slotnum, unsigned long offset) +{ + return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset)); +} + +extern __inline__ int sbus_dev_slot(unsigned long dev_addr) +{ + return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25); +} + +extern __inline__ unsigned long sbus_dev_offset(unsigned long dev_addr) +{ + return (unsigned long) (((dev_addr)-SUN_SBUS_BVADDR)&SBUS_OFF_MASK); +} + +struct linux_sbus; + +/* Linux SBUS device tables */ +struct linux_sbus_device { + struct linux_sbus_device *next; /* next device on this SBus or null */ + struct linux_sbus_device *child; /* For ledma and espdma on sun4m */ + struct linux_sbus *my_bus; /* Back ptr to sbus */ + int prom_node; /* PROM device tree node for this device */ + char prom_name[64]; /* PROM device name */ + char linux_name[64]; /* Name used internally by Linux */ + + struct linux_prom_registers reg_addrs[PROMREG_MAX]; + int num_registers; + + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int num_irqs; + + unsigned long sbus_addr; /* Absolute base address for device. */ + unsigned long sbus_vaddrs[PROMVADDR_MAX]; + unsigned long num_vaddrs; + unsigned long offset; /* Offset given by PROM */ + int slot; +}; + +/* This struct describes the SBus(s) found on this machine. */ +struct linux_sbus { + struct linux_sbus *next; /* next SBus, if more than one SBus */ + struct linux_sbus_device *devices; /* Link to devices on this SBus */ + struct iommu_struct *iommu; /* IOMMU for this sbus if applicable */ + int prom_node; /* PROM device tree node for this SBus */ + char prom_name[64]; /* Usually "sbus" or "sbi" */ + int clock_freq; + struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; + int num_sbus_ranges; +}; + +extern struct linux_sbus *SBus_chain; + +extern __inline__ int +sbus_is_slave(struct linux_sbus_device *dev) +{ + /* Have to write this for sun4c's */ + return 0; +} + +/* Device probing routines could find these handy */ +#define for_each_sbus(bus) \ + for((bus) = SBus_chain; (bus); (bus)=(bus)->next) + +#define for_each_sbusdev(device, bus) \ + for((device) = (bus)->devices; (device); (device)=(device)->next) + +#define for_all_sbusdev(device, bus) \ + for((bus) = SBus_chain, (device) = (bus)->devices; (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) + +/* Apply promlib probed SBUS ranges to registers. */ +extern void prom_apply_sbus_ranges(struct linux_sbus *sbus, + struct linux_prom_registers *sbusregs, int nregs); + +#endif /* !(_SPARC_SBUS_H) */ diff --git a/include/asm-sparc/segment.h b/include/asm-sparc/segment.h index 27489b3e5..a1b7ffc9e 100644 --- a/include/asm-sparc/segment.h +++ b/include/asm-sparc/segment.h @@ -1,87 +1,6 @@ -#ifndef _ASM_SEGMENT_H -#define _ASM_SEGMENT_H +#ifndef __SPARC_SEGMENT_H +#define __SPARC_SEGMENT_H -#define KERNEL_CS 0x0 -#define KERNEL_DS 0x0 +/* Only here because we have some old header files that expect it.. */ -#define USER_CS 0x1 -#define USER_DS 0x1 - -#include <linux/string.h> -#include <asm/vac-ops.h> - -static inline unsigned char get_user_byte(const char * addr) -{ - return *addr; -} - -#define get_fs_byte(addr) get_user_byte((char *)(addr)) - -static inline unsigned short get_user_word(const short *addr) -{ - return *addr; -} - -#define get_fs_word(addr) get_user_word((short *)(addr)) - -static inline unsigned long get_user_long(const int *addr) -{ - return *addr; -} - -#define get_fs_long(addr) get_user_long((int *)(addr)) - -static inline unsigned long get_user_quad(const long *addr) -{ - return *addr; -} - -#define get_fs_quad(addr) get_user_quad((long *)(addr)) - -static inline void put_user_byte(char val,char *addr) -{ - *addr = val; -} - -#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr)) - -static inline void put_user_word(short val,short * addr) -{ - *addr = val; -} - -#define put_fs_word(x,addr) put_user_word((x),(short *)(addr)) - -static inline void put_user_long(unsigned long val,int * addr) -{ - *addr = val; -} - -#define put_fs_long(x,addr) put_user_long((x),(int *)(addr)) - -static inline void put_user_quad(unsigned long val,long * addr) -{ - *addr = val; -} - -#define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr)) - -#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n)) - -#define memcpy_tofs(to, from, n) memcpy((to),(from),(n)) - -static inline unsigned long get_fs(void) -{ - return 0; -} - -static inline unsigned long get_ds(void) -{ - return 0; -} - -static inline void set_fs(unsigned long val) -{ -} - -#endif /* _ASM_SEGMENT_H */ +#endif diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h new file mode 100644 index 000000000..4892ccb26 --- /dev/null +++ b/include/asm-sparc/semaphore.h @@ -0,0 +1,42 @@ +#ifndef _SPARC_SEMAPHORE_H +#define _SPARC_SEMAPHORE_H + +/* Dinky, good for nothing, just barely irq safe, Sparc semaphores. + * + * I'll write better ones later. + */ + +#include <asm/atomic.h> + +struct semaphore { + atomic_t count; + atomic_t waiting; + struct wait_queue * wait; +}; + +#define MUTEX ((struct semaphore) { 1, 0, NULL }) +#define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL }) + +extern void __down(struct semaphore * sem); +extern void __up(struct semaphore * sem); + +/* + * This isn't quite as clever as the x86 side, but the gp register + * makes things a bit more complicated on the alpha.. + */ +extern inline void down(struct semaphore * sem) +{ + for (;;) { + if (atomic_dec_return(&sem->count) >= 0) + break; + __down(sem); + } +} + +extern inline void up(struct semaphore * sem) +{ + if (atomic_inc_return(&sem->count) <= 0) + __up(sem); +} + +#endif /* !(_SPARC_SEMAPHORE_H) */ diff --git a/include/asm-sparc/shmparam.h b/include/asm-sparc/shmparam.h new file mode 100644 index 000000000..54420d89d --- /dev/null +++ b/include/asm-sparc/shmparam.h @@ -0,0 +1,45 @@ +/* $Id: shmparam.h,v 1.3 1995/11/25 02:32:42 davem Exp $ */ +#ifndef _ASMSPARC_SHMPARAM_H +#define _ASMSPARC_SHMPARAM_H + +/* address range for shared memory attaches if no address passed to shmat() */ +#define SHM_RANGE_START 0x10000000 +#define SHM_RANGE_END 0x20000000 + +/* + * Format of a swap-entry for shared memory pages currently out in + * swap space (see also mm/swap.c). + * + * SWP_TYPE = SHM_SWP_TYPE + * SWP_OFFSET is used as follows: + * + * bits 0..6 : id of shared memory segment page belongs to (SHM_ID) + * bits 7..21: index of page within shared memory segment (SHM_IDX) + * (actually fewer bits get used since SHMMAX is so low) + */ + +/* + * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and + * there is a static array of size SHMMNI. + */ +#define _SHM_ID_BITS 7 +#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1) + +#define SHM_IDX_SHIFT (_SHM_ID_BITS) +#define _SHM_IDX_BITS 15 +#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1) + +/* + * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and + * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). + */ + +#define SHMMAX (1024 * 1024) /* max shared seg size (bytes) */ +#define SHMMIN 1 /* really PAGE_SIZE */ /* min shared seg size (bytes) */ +#define SHMMNI (1<<_SHM_ID_BITS) /* max num of segs system wide */ +#define SHMALL /* max shm system wide (pages) */ \ + (1<<(_SHM_IDX_BITS+_SHM_ID_BITS)) +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ +#define SHMSEG SHMMNI /* max shared segs per process */ + +#endif /* _ASMSPARC_SHMPARAM_H */ diff --git a/include/asm-sparc/sigcontext.h b/include/asm-sparc/sigcontext.h new file mode 100644 index 000000000..c7a9993fe --- /dev/null +++ b/include/asm-sparc/sigcontext.h @@ -0,0 +1,42 @@ +/* $Id: sigcontext.h,v 1.9 1996/10/27 08:55:42 davem Exp $ */ +#ifndef _ASMsparc_SIGCONTEXT_H +#define _ASMsparc_SIGCONTEXT_H + +#include <asm/ptrace.h> + +#define SUNOS_MAXWIN 31 + +#ifndef __ASSEMBLY__ + +/* SunOS system call sigstack() uses this arg. */ +struct sunos_sigstack { + unsigned long sig_sp; + int onstack_flag; +}; + +/* This is what SunOS does, so shall I. */ +struct sigcontext { + int sigc_onstack; /* state to restore */ + int sigc_mask; /* sigmask to restore */ + int sigc_sp; /* stack pointer */ + int sigc_pc; /* program counter */ + int sigc_npc; /* next program counter */ + int sigc_psr; /* for condition codes etc */ + int sigc_g1; /* User uses these two registers */ + int sigc_o0; /* within the trampoline code. */ + + /* Now comes information regarding the users window set + * at the time of the signal. + */ + int sigc_oswins; /* outstanding windows */ + + /* stack ptrs for each regwin buf */ + char *sigc_spbuf[SUNOS_MAXWIN]; + + /* Windows to restore after signal */ + struct reg_window sigc_wbuf[SUNOS_MAXWIN]; +}; +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_ASMsparc_SIGCONTEXT_H) */ + diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h index 2e599e18d..2cc321d13 100644 --- a/include/asm-sparc/signal.h +++ b/include/asm-sparc/signal.h @@ -1,11 +1,177 @@ +/* $Id: signal.h,v 1.29 1996/10/27 08:55:45 davem Exp $ */ #ifndef _ASMSPARC_SIGNAL_H #define _ASMSPARC_SIGNAL_H -struct sigcontext_struct { - /* - * Have to find out what SUNOS and Solaris do. This could - * get real ugly. David S. Miller (davem@caip.rutgers.edu) - */ +#include <asm/sigcontext.h> + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#include <linux/personality.h> +#endif +#endif + +/* On the Sparc the signal handlers get passed a 'sub-signal' code + * for certain signal types, which we document here. + */ +#define _NSIG 32 +#define NSIG _NSIG + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SUBSIG_STACK 0 +#define SUBSIG_ILLINST 2 +#define SUBSIG_PRIVINST 3 +#define SUBSIG_BADTRAP(t) (0x80 + (t)) + +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 + +#define SIGEMT 7 +#define SUBSIG_TAG 10 + +#define SIGFPE 8 +#define SUBSIG_FPDISABLED 0x400 +#define SUBSIG_FPERROR 0x404 +#define SUBSIG_FPINTOVFL 0x001 +#define SUBSIG_FPSTSIG 0x002 +#define SUBSIG_IDIVZERO 0x014 +#define SUBSIG_FPINEXACT 0x0c4 +#define SUBSIG_FPDIVZERO 0x0c8 +#define SUBSIG_FPUNFLOW 0x0cc +#define SUBSIG_FPOPERROR 0x0d0 +#define SUBSIG_FPOVFLOW 0x0d4 + +#define SIGKILL 9 +#define SIGBUS 10 +#define SUBSIG_BUSTIMEOUT 1 +#define SUBSIG_ALIGNMENT 2 +#define SUBSIG_MISCERROR 5 + +#define SIGSEGV 11 +#define SUBSIG_NOMAPPING 3 +#define SUBSIG_PROTECTION 4 +#define SUBSIG_SEGERROR 5 + +#define SIGSYS 12 + +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 + +/* SunOS values which deviate from the Linux/i386 ones */ +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGPOLL SIGIO /* SysV name for SIGIO */ +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGLOST 29 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#ifndef __ASSEMBLY__ + +typedef unsigned long sigset_t; + +#ifdef __KERNEL__ +#include <asm/sigcontext.h> +#endif + +/* A SunOS sigstack */ +struct sigstack { + char *the_stack; + int cur_status; }; +/* Sigvec flags */ +#define SV_SSTACK 1 /* This signal handler should use sig-stack */ +#define SV_INTR 2 /* Sig return should not restart system call */ +#define SV_RESET 4 /* Set handler to SIG_DFL upon taken signal */ +#define SV_IGNCHILD 8 /* Do not send SIGCHLD */ + +/* + * sa_flags values: SA_STACK is not currently supported, but will allow the + * usage of signal stacks by using the (now obsolete) sa_restorer field in + * the sigaction structure as a stack pointer. This is now possible due to + * the changes in signal handling. LBT 010493. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. + */ +#define SA_NOCLDSTOP SV_IGNCHILD +#define SA_STACK SV_SSTACK +#define SA_RESTART SV_INTR +#define SA_ONESHOT SV_RESET +#define SA_INTERRUPT 0x10 +#define SA_NOMASK 0x20 +#define SA_SHIRQ 0x40 + +#define SIG_BLOCK 0x01 /* for blocking signals */ +#define SIG_UNBLOCK 0x02 /* for unblocking signals */ +#define SIG_SETMASK 0x04 /* for setting the signal mask */ + +#ifdef __KERNEL__ +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * + * DJHR + * SA_STATIC_ALLOC is used for the SPARC system to indicate that this + * interrupt handler's irq structure should be statically allocated + * by the request_irq routine. + * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge + * of interrupt usage and that sucks. Also without a flag like this + * it may be possible for the free_irq routine to attempt to free + * statically allocated data.. which is NOT GOOD. + * + */ +#define SA_PROBE SA_ONESHOT +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_STATIC_ALLOC 0x80 +#endif + +/* Type of a signal handler. */ +#ifdef __KERNEL__ +typedef void (*__sighandler_t)(int, int, struct sigcontext *, char *); +#else +typedef void (*__sighandler_t)(int); #endif + +#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ +#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ +#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ + +struct sigaction { + __sighandler_t sa_handler; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer) (void); /* not used by Linux/SPARC yet */ +}; + +#ifdef __KERNEL__ + +/* use the following macro to get the size of a sigaction struct + when copying to/from userland */ +#define SIGACTION_SIZE(personality) (((personality) & PER_BSD)?\ + sizeof(struct sigaction)-sizeof(void *):\ + sizeof(struct sigaction)) + +#endif /* __KERNEL__ */ + + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_ASMSPARC_SIGNAL_H) */ diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h new file mode 100644 index 000000000..0d1cab1eb --- /dev/null +++ b/include/asm-sparc/smp.h @@ -0,0 +1,172 @@ +/* smp.h: Sparc specific SMP stuff. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_SMP_H +#define _SPARC_SMP_H + +#ifndef __ASSEMBLY__ +/* PROM provided per-processor information we need + * to start them all up. + */ + +struct prom_cpuinfo { + int prom_node; + int mid; +}; +#endif /* !(__ASSEMBLY__) */ + +#ifdef __SMP__ + +#ifndef __ASSEMBLY__ + +extern struct prom_cpuinfo linux_cpus[NCPUS]; + +/* Per processor Sparc parameters we need. */ + +struct cpuinfo_sparc { + unsigned long udelay_val; /* that's it */ +}; + +extern struct cpuinfo_sparc cpu_data[NR_CPUS]; + +typedef __volatile__ unsigned char klock_t; +extern klock_t kernel_flag; + +#define KLOCK_HELD 0xff +#define KLOCK_CLEAR 0x00 + +/* + * Private routines/data + */ + +extern int smp_found_cpus; +extern unsigned char boot_cpu_id; +extern unsigned long cpu_present_map; +extern __volatile__ unsigned long smp_invalidate_needed[NR_CPUS]; +extern __volatile__ unsigned long kernel_counter; +extern __volatile__ unsigned char active_kernel_processor; +extern void smp_message_irq(void); +extern unsigned long ipi_count; +extern __volatile__ unsigned long kernel_counter; +extern __volatile__ unsigned long syscall_count; + +extern void print_lock_state(void); + +typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long); + +/* + * General functions that each host system must provide. + */ + +extern void smp_callin(void); +extern void smp_boot_cpus(void); +extern void smp_store_cpu_info(int id); +extern void smp_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, unsigned long arg5); +extern void smp_capture(void); +extern void smp_release(void); + +extern __inline__ void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); } +extern __inline__ void xc1(smpfunc_t func, unsigned long arg1) +{ smp_cross_call(func, arg1, 0, 0, 0, 0); } +extern __inline__ void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) +{ smp_cross_call(func, arg1, arg2, 0, 0, 0); } +extern __inline__ void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, + unsigned long arg3) +{ smp_cross_call(func, arg1, arg2, arg3, 0, 0); } +extern __inline__ void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4) +{ smp_cross_call(func, arg1, arg2, arg3, arg4, 0); } +extern __inline__ void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, unsigned long arg5) +{ smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); } + +extern __volatile__ int cpu_number_map[NR_CPUS]; +extern __volatile__ int cpu_logical_map[NR_CPUS]; + +extern __inline__ int smp_processor_id(void) +{ + int cpuid; + + __asm__ __volatile__("rd %%tbr, %0\n\t" + "srl %0, 12, %0\n\t" + "and %0, 3, %0\n\t" : + "=&r" (cpuid)); + return cpuid; +} + + +extern __volatile__ unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */ +extern __volatile__ int smp_process_available; + +extern __inline__ int smp_swap(volatile int *addr, int value) +{ + __asm__ __volatile__("swap [%2], %0\n\t" : + "=&r" (value) : + "0" (value), "r" (addr)); + return value; +} + +extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr) +{ + int tmp; + + while((tmp = smp_swap(ctr, -1)) == -1) + while(*ctr == -1) + ; + + *ctr = (tmp + 1); +} + +extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr) +{ + int tmp; + + while((tmp = smp_swap(ctr, -1)) == -1) + while(*ctr == -1) + ; + + *ctr = (tmp - 1); +} + +extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr) +{ + int value; + + while((value = *ctr) == -1) + ; + + return value; +} + +#endif /* !(__ASSEMBLY__) */ + +/* Sparc specific messages. */ +#define MSG_CAPTURE 0x0004 /* Park a processor. */ +#define MSG_CROSS_CALL 0x0005 /* run func on cpus */ + +/* Empirical PROM processor mailbox constants. If the per-cpu mailbox + * contains something other than one of these then the ipi is from + * Linux's active_kernel_processor. This facility exists so that + * the boot monitor can capture all the other cpus when one catches + * a watchdog reset or the user enters the monitor using L1-A keys. + */ +#define MBOX_STOPCPU 0xFB +#define MBOX_IDLECPU 0xFC +#define MBOX_IDLECPU2 0xFD +#define MBOX_STOPCPU2 0xFE + + +#define NO_PROC_ID 0xFF + +#define PROC_CHANGE_PENALTY 20 + +#define SMP_FROM_INT 1 +#define SMP_FROM_SYSCALL 2 + +#endif /* !(__SMP__) */ + +#endif /* !(_SPARC_SMP_H) */ diff --git a/include/asm-sparc/smp_lock.h b/include/asm-sparc/smp_lock.h new file mode 100644 index 000000000..7ce71d8ff --- /dev/null +++ b/include/asm-sparc/smp_lock.h @@ -0,0 +1,60 @@ +/* smp_lock.h: Locking and unlocking the kernel on the Sparc. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __SPARC_SMPLOCK_H +#define __SPARC_SMPLOCK_H + +#include <asm/smp.h> +#include <asm/bitops.h> +#include <asm/atops.h> +#include <asm/pgtable.h> + +#ifdef __SMP__ + +/* + * Locking the kernel + */ + +/* Knock knock... */ +extern __inline__ void lock_kernel(void) +{ + unsigned long flags; + int proc = smp_processor_id(); + + save_flags(flags); cli(); /* need this on sparc? */ + while(ldstub(&kernel_flag)) { + if(proc == active_kernel_processor) + break; + do { +#ifdef __SMP_PROF__ + smp_spins[smp_processor_id()]++; +#endif + barrier(); + } while(kernel_flag); /* Don't lock the bus more than we have to. */ + } + active_kernel_processor = proc; + kernel_counter++; + restore_flags(flags); +} + +/* I want out... */ +extern __inline__ void unlock_kernel(void) +{ + unsigned long flags; + + save_flags(flags); cli(); /* need this on sparc? */ + if(kernel_counter == 0) + panic("Bogus kernel counter.\n"); + + if(!--kernel_counter) { + active_kernel_processor = NO_PROC_ID; + kernel_flag = KLOCK_CLEAR; + } + restore_flags(flags); +} + +#endif /* !(__SPARC_SMPLOCK_H) */ + +#endif /* (__SMP__) */ diff --git a/include/asm-sparc/smpprim.h b/include/asm-sparc/smpprim.h new file mode 100644 index 000000000..9b9c28ed7 --- /dev/null +++ b/include/asm-sparc/smpprim.h @@ -0,0 +1,54 @@ +/* $Id: smpprim.h,v 1.5 1996/08/29 09:48:49 davem Exp $ + * smpprim.h: SMP locking primitives on the Sparc + * + * God knows we won't be actually using this code for some time + * but I thought I'd write it since I knew how. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __SPARC_SMPPRIM_H +#define __SPARC_SMPPRIM_H + +/* Test and set the unsigned byte at ADDR to 1. Returns the previous + * value. On the Sparc we use the ldstub instruction since it is + * atomic. + */ + +extern __inline__ __volatile__ char test_and_set(void *addr) +{ + char state = 0; + + __asm__ __volatile__("ldstub [%0], %1 ! test_and_set\n\t" + "=r" (addr), "=r" (state) : + "0" (addr), "1" (state) : "memory"); + + return state; +} + +/* Initialize a spin-lock. */ +extern __inline__ __volatile__ smp_initlock(void *spinlock) +{ + /* Unset the lock. */ + *((unsigned char *) spinlock) = 0; + + return; +} + +/* This routine spins until it acquires the lock at ADDR. */ +extern __inline__ __volatile__ smp_lock(void *addr) +{ + while(test_and_set(addr) == 0xff) + ; + + /* We now have the lock */ + return; +} + +/* This routine releases the lock at ADDR. */ +extern __inline__ __volatile__ smp_unlock(void *addr) +{ + *((unsigned char *) addr) = 0; +} + +#endif /* !(__SPARC_SMPPRIM_H) */ diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h new file mode 100644 index 000000000..1c5348030 --- /dev/null +++ b/include/asm-sparc/socket.h @@ -0,0 +1,32 @@ +/* $Id: socket.h,v 1.6 1996/04/04 12:51:26 davem Exp $ */ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +#include <asm/sockios.h> + +/* For setsockoptions(2) */ +#define SOL_SOCKET 0xffff + +#define SO_DEBUG 0x0001 +#define SO_REUSEADDR 0x0004 +#define SO_KEEPALIVE 0x0008 +#define SO_DONTROUTE 0x0010 +#define SO_BROADCAST 0x0020 +#define SO_LINGER 0x0080 +#define SO_OOBINLINE 0x0100 +/* To add :#define SO_REUSEPORT 0x0200 */ +#define SO_BSDCOMPAT 0x0400 + +/* wha!??? */ +#define SO_DONTLINGER (~SO_LINGER) /* Older SunOS compat. hack */ + +#define SO_SNDBUF 0x1001 +#define SO_RCVBUF 0x1002 +#define SO_ERROR 0x1007 +#define SO_TYPE 0x1008 + +/* Linux specific, keep the same. */ +#define SO_NO_CHECK 0x000b +#define SO_PRIORITY 0x000c + +#endif /* _ASM_SOCKET_H */ diff --git a/include/asm-sparc/sockios.h b/include/asm-sparc/sockios.h new file mode 100644 index 000000000..0c01b597b --- /dev/null +++ b/include/asm-sparc/sockios.h @@ -0,0 +1,13 @@ +#ifndef _ASM_SPARC_SOCKIOS_H +#define _ASM_SPARC_SOCKIOS_H + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ + +#endif /* !(_ASM_SPARC_SOCKIOS_H) */ + diff --git a/include/asm-sparc/solerrno.h b/include/asm-sparc/solerrno.h new file mode 100644 index 000000000..8abce7e46 --- /dev/null +++ b/include/asm-sparc/solerrno.h @@ -0,0 +1,132 @@ +/* $Id: solerrno.h,v 1.5 1996/04/25 06:13:32 davem Exp $ + * solerrno.h: Solaris error return codes for compatibility. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_SOLERRNO_H +#define _SPARC_SOLERRNO_H + +#define SOL_EPERM 1 /* Required superuser access perms */ +#define SOL_ENOENT 2 /* File or directory does not exist */ +#define SOL_ESRCH 3 /* Process did not exist */ +#define SOL_EINTR 4 /* System call was interrupted */ +#define SOL_EIO 5 /* An i/o error occurred */ +#define SOL_ENXIO 6 /* Device or Address does not exist */ +#define SOL_E2BIG 7 /* Too many arguments were given */ +#define SOL_ENOEXEC 8 /* Header of executable was munged */ +#define SOL_EBADF 9 /* Bogus file number */ +#define SOL_ECHILD 10 /* No children of process exist */ +#define SOL_EAGAIN 11 /* beep beep, "try again later" */ +#define SOL_ENOMEM 12 /* No memory available */ +#define SOL_EACCES 13 /* Access not allowed */ +#define SOL_EFAULT 14 /* Address passed was invalid */ +#define SOL_ENOTBLK 15 /* blkdev op on non-block device */ +#define SOL_EBUSY 16 /* Mounted device was busy */ +#define SOL_EEXIST 17 /* File specified already exists */ +#define SOL_EXDEV 18 /* Link request across diff devices */ +#define SOL_ENODEV 19 /* Device does not exist on system */ +#define SOL_ENOTDIR 20 /* Dir operation on non-directory */ +#define SOL_EISDIR 21 /* File was of directory type */ +#define SOL_EINVAL 22 /* Argument passed was invalid */ +#define SOL_ENFILE 23 /* No more room in file table */ +#define SOL_EMFILE 24 /* Proc has too many files open */ +#define SOL_ENOTTY 25 /* Ioctl was invalid for req device */ +#define SOL_ETXTBSY 26 /* Text file in busy state */ +#define SOL_EFBIG 27 /* Too big of a file for operation */ +#define SOL_ENOSPC 28 /* Disk is full */ +#define SOL_ESPIPE 29 /* Seek attempted on non-seeking dev*/ +#define SOL_EROFS 30 /* Write attempted on read-only fs */ +#define SOL_EMLINK 31 /* Too many links in file search */ +#define SOL_EPIPE 32 /* Call a plumber */ +#define SOL_EDOM 33 /* Argument was out of fct domain */ +#define SOL_ERANGE 34 /* Could not represent math result */ +#define SOL_ENOMSG 35 /* Message of req type doesn't exist */ +#define SOL_EIDRM 36 /* Identifier has been removed */ +#define SOL_ECHRNG 37 /* Req channel number out of range */ +#define SOL_EL2NSYNC 38 /* Could not sync at run level 2 */ +#define SOL_EL3HLT 39 /* Halted at run level 3 */ +#define SOL_EL3RST 40 /* Reset at run level 3 */ +#define SOL_ELNRNG 41 /* Out of range link number */ +#define SOL_EUNATCH 42 /* Driver for protocol not attached */ +#define SOL_ENOCSI 43 /* CSI structure not around */ +#define SOL_EL2HLT 44 /* Halted at run level 2 */ +#define SOL_EDEADLK 45 /* Deadlock condition detected */ +#define SOL_ENOLCK 46 /* Record locks unavailable */ +#define SOL_ECANCELED 47 /* Cancellation of oper. happened */ +#define SOL_ENOTSUP 48 /* Attempt of unsupported operation */ +#define SOL_EDQUOT 49 /* Users disk quota exceeded */ +#define SOL_EBADE 50 /* Invalid exchange */ +#define SOL_EBADR 51 /* Request descriptor was invalid */ +#define SOL_EXFULL 52 /* Full exchange */ +#define SOL_ENOANO 53 /* ano does not exist */ +#define SOL_EBADRQC 54 /* Req code was invalid */ +#define SOL_EBADSLT 55 /* Bad slot number */ +#define SOL_EDEADLOCK 56 /* Deadlock in fs error */ +#define SOL_EBFONT 57 /* Font file format invalid */ +/* YOW, I LOVE SYSV STREAMS!!!! */ +#define SOL_ENOSTR 60 /* Stream-op on non-stream dev */ +#define SOL_ENODATA 61 /* No data avail at this time */ +#define SOL_ETIME 62 /* Expiration of time occurred */ +#define SOL_ENOSR 63 /* Streams resources exhausted */ +#define SOL_ENONET 64 /* No network connected */ +#define SOL_ENOPKG 65 /* Non-installed package */ +#define SOL_EREMOTE 66 /* Object was on remote machine */ +#define SOL_ENOLINK 67 /* Cut link */ +#define SOL_EADV 68 /* Error in advertise */ +#define SOL_ESRMNT 69 /* Some magic srmount problem */ +#define SOL_ECOMM 70 /* During send, comm error occurred */ +#define SOL_EPROTO 71 /* Protocol botch */ +#define SOL_EMULTIHOP 74 /* Multihop attempted */ +#define SOL_EBADMSG 77 /* Message was unreadable */ +#define SOL_ENAMETOOLONG 78 /* Too long of a path name */ +#define SOL_EOVERFLOW 79 /* Data type too small for datum */ +#define SOL_ENOTUNIQ 80 /* Logical name was not unique */ +#define SOL_EBADFD 81 /* Op cannot be performed on fd */ +#define SOL_EREMCHG 82 /* Remote address is now different */ +#define SOL_ELIBACC 83 /* Shared lib could not be accessed */ +#define SOL_ELIBBAD 84 /* ShLib is corrupted in some way */ +#define SOL_ELIBSCN 85 /* A.out ShLib problems */ +#define SOL_ELIBMAX 86 /* Exceeded ShLib linkage limit */ +#define SOL_ELIBEXEC 87 /* Execution of ShLib attempted */ +#define SOL_EILSEQ 88 /* Bad byte sequence found */ +#define SOL_ENOSYS 89 /* Invalid filesystem operation */ +#define SOL_ELOOP 90 /* Detected loop in symbolic links */ +#define SOL_ERESTART 91 /* System call is restartable */ +#define SOL_ESTRPIPE 92 /* Do not sleep in head of stream */ +#define SOL_ENOTEMPTY 93 /* Rmdir of non-empty directory */ +#define SOL_EUSERS 94 /* Over abundance of users for ufs */ +#define SOL_ENOTSOCK 95 /* Sock-op on non-sock */ +#define SOL_EDESTADDRREQ 96 /* No dest addr given, but needed */ +#define SOL_EMSGSIZE 97 /* Msg too big */ +#define SOL_EPROTOTYPE 98 /* Bad socket protocol */ +#define SOL_ENOPROTOOPT 99 /* Unavailable protocol */ +#define SOL_EPROTONOSUPPORT 120 /* Unsupported protocol */ +#define SOL_ESOCKTNOSUPPORT 121 /* Unsupported socket type */ +#define SOL_EOPNOTSUPP 122 /* Unsupported sock-op */ +#define SOL_EPFNOSUPPORT 123 /* Unsupported protocol family */ +#define SOL_EAFNOSUPPORT 124 /* Unsup addr family for protocol */ +#define SOL_EADDRINUSE 125 /* Req addr is already in use */ +#define SOL_EADDRNOTAVAIL 126 /* Req addr not available right now */ +#define SOL_ENETDOWN 127 /* Your subnet is on fire */ +#define SOL_ENETUNREACH 128 /* Someone playing with gateway and */ + /* did not tell you he was going to */ +#define SOL_ENETRESET 129 /* Buy less-buggy ethernet cards */ +#define SOL_ECONNABORTED 130 /* Aborted connection due to sw */ +#define SOL_ECONNRESET 131 /* Your peers reset your connection */ +#define SOL_ENOBUFS 132 /* No buffer space available */ +#define SOL_EISCONN 133 /* Connect on already connected */ + /* socket attempted */ +#define SOL_ENOTCONN 134 /* Comm on non-connected socket */ +#define SOL_ESHUTDOWN 143 /* Op attempted after sock-shutdown */ +#define SOL_ETOOMANYREFS 144 /* Reference limit exceeded */ +#define SOL_ETIMEDOUT 145 /* Timed out connection */ +#define SOL_ECONNREFUSED 146 /* Connection refused by remote host*/ +#define SOL_EHOSTDOWN 147 /* Remote host is up in flames */ +#define SOL_EHOSTUNREACH 148 /* Make a left at Easton Ave..... */ +#define SOL_EWOULDBLOCK EAGAIN /* Just an alias */ +#define SOL_EALREADY 149 /* Operation is already occurring */ +#define SOL_EINPROGRESS 150 /* Operation is happening now */ +#define SOL_ESTALE 151 /* Fungus growth on NFS file handle */ + +#endif /* !(_SPARC_SOLERRNO_H) */ diff --git a/include/asm-sparc/stat.h b/include/asm-sparc/stat.h new file mode 100644 index 000000000..35f929c56 --- /dev/null +++ b/include/asm-sparc/stat.h @@ -0,0 +1,41 @@ +/* $Id: stat.h,v 1.7 1996/10/27 08:55:48 davem Exp $ */ +#ifndef _SPARC_STAT_H +#define _SPARC_STAT_H + +#include <linux/types.h> + +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; + +struct stat { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + short st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + unsigned long __unused1; + time_t st_mtime; + unsigned long __unused2; + time_t st_ctime; + unsigned long __unused3; + off_t st_blksize; + off_t st_blocks; + unsigned long __unused4[2]; +}; + +#endif diff --git a/include/asm-sparc/statfs.h b/include/asm-sparc/statfs.h new file mode 100644 index 000000000..91a19b92a --- /dev/null +++ b/include/asm-sparc/statfs.h @@ -0,0 +1,26 @@ +/* $Id: statfs.h,v 1.4 1996/06/07 00:41:05 ecd Exp $ */ +#ifndef _SPARC_STATFS_H +#define _SPARC_STATFS_H + +#ifndef __KERNEL_STRICT_NAMES + +#include <linux/types.h> + +typedef __kernel_fsid_t fsid_t; + +#endif + +struct statfs { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; /* SunOS ignores this field. */ + long f_spare[6]; +}; + +#endif diff --git a/include/asm-sparc/string.h b/include/asm-sparc/string.h index 6e0bfc1f7..856e96f6d 100644 --- a/include/asm-sparc/string.h +++ b/include/asm-sparc/string.h @@ -1,367 +1,178 @@ -/* string.h: External definitions for optimized assembly string - routines for the Linux Kernel. +/* $Id: string.h,v 1.27 1996/10/27 08:55:50 davem Exp $ + * string.h: External definitions for optimized assembly string + * routines for the Linux Kernel. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ +#ifndef __SPARC_STRING_H__ +#define __SPARC_STRING_H__ -extern inline size_t strlen(const char * str) -{ - register size_t retval = 0; - register char tmp = 0; - register char * lstr; - - lstr = (char *) str; - - __asm__("ldub [%1], %2\n\t" - "or %%g0, %%g0, %0\n\t" - "orcc %2, %%g0, %%g0\n\t" - "be 2f\n\t" - "add %1, 0x1, %1\n\t" - "1: ldub [%1], %2\n\t" - "add %0, 0x1, %0\n\t" - "orcc %2, %%g0, %%g0\n\t" - "bne 1b\n\t" - "add %1, 0x1, %1\n\t" - "2:" : - "=r" (retval), "=r" (lstr), "=r" (tmp) : - "0" (retval), "1" (lstr), "2" (tmp)); - - return retval; -} - -extern __inline__ int strcmp(const char* str1, const char* str2) -{ - register unsigned int tmp1=0, tmp2=0; - register int retval=0; - - __asm__("ldub [%1], %3\n\t" - "ldub [%2], %4\n\t" - "1: add %2, 0x1, %2\n\t" - "cmp %3, %4\n\t" - "bne,a 2f\n\t" - "sub %2, 0x1, %2\n\t" - "ldub [%1], %3\n\t" - "add %1, 0x1, %1\n\t" - "cmp %3, 0x0\n\t" - "bne,a 1b\n\t" - "ldub [%2], %4\n\t" - "b 3f\n\t" - "or %%g0, %%g0, %0\n\t" - "2: ldub [%1], %3\n\t" - "ldub [%2], %4\n\t" - "sub %3, %4, %0\n\t" - "3: \n\t" : - "=r" (retval), "=r" (str1), "=r" (str2), "=r" (tmp1), "=r" (tmp2) : - "0" (retval), "1" (str1), "2" (str2), - "3" (tmp1), "4" (tmp2)); - - return retval; -} - -extern __inline__ int strncmp(const char* str1, const char* str2, size_t strlen) -{ - register int retval=0; - - __asm__("cmp %3, 0x0\n\t" - "be 2f\n\t" - "ldub [%2], %%g3\n\t" - "1: ldub [%1], %%g2\n\t" - "sub %%g2, %%g3, %0\n\t" - "cmp %0, 0x0\n\t" - "bne 2f\n\t" - "add %2, 0x1, %2\n\t" - "cmp %%g2, 0x0\n\t" - "be 2f\n\t" - "add %1, 0x1, %1\n\t" - "addcc %3, -1, %3\n\t" - "bne,a 1b\n\t" - "ldub [%2], %%g3\n\t" - "2: " : - "=r" (retval), "=r" (str1), "=r" (str2), "=r" (strlen) : - "0" (retval), "1" (str1), "2" (str2), "3" (strlen) : - "%g2", "%g3"); - - return retval; -} +/* Really, userland/ksyms should not see any of this stuff. */ +#if defined(__KERNEL__) && !defined(EXPORT_SYMTAB) -extern __inline__ char *strcpy(char* dest, const char* source) -{ - register char tmp; - register char *retval; - - __asm__("or %%g0, %2, %0\n\t" - "ldub [%1], %3\n\t" - "1: stb %3, [%2]\n\t" - "cmp %3, 0x0\n\t" - "bne,a 1b\n\t" - "ldub [%1], %3\n\t" : - "=r" (retval), "=r" (source), "=r" (dest), "=r" (tmp) : - "0" (retval), "1" (source), "2" (dest), "3" (tmp)); - - return retval; -} +/* First the mem*() things. */ +#define __HAVE_ARCH_BCOPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMCPY +extern void *__memcpy(void *,const void *,__kernel_size_t); -extern __inline__ char *strncpy(char *dest, const char *source, size_t cpylen) +extern inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n) { - register char tmp; - register char *retval; - - __asm__("or %%g0, %1, %0\n\t" - "1: cmp %4, 0x0\n\t" - "be 2f\n\t" - "ldub [%1], %3\n\t" - "add %1, 0x1, %1\n\t" - "stb %3, [%2]\n\t" - "sub %4, 0x1, %4\n\t" - "ba 1\n\t" - "add %2, 0x1, %2\n\t" : - "=r" (retval), "=r" (dest), "=r" (source), "=r"(tmp), "=r" (cpylen) : - "0" (retval), "1" (dest), "2" (source), - "3" (tmp), "4" (cpylen)); - - return retval; -} - -extern __inline__ char *strcat(char *dest, const char *src) -{ - register char *retval; - register char temp=0; - - __asm__("or %%g0, %1, %0\n\t" - "1: ldub [%1], %3\n\t" - "cmp %3, 0x0\n\t" - "bne,a 1b\n\t" - "add %1, 0x1, %1\n\t" - "2: ldub [%2], %3\n\t" - "stb %3, [%1]\n\t" - "add %1, 0x1, %1\n\t" - "cmp %3, 0x0\n\t" - "bne 2b\n\t" - "add %2, 0x1, %2\n\t" : - "=r" (retval), "=r" (dest), "=r" (src), "=r" (temp) : - "0" (retval), "1" (dest), "2" (src), "3" (temp)); - - return retval; -} - -extern __inline__ char *strncat(char *dest, const char *src, size_t len) -{ - register char *retval; - register char temp=0; - - __asm__("or %%g0, %1, %0\n\t" - "1: ldub [%1], %3\n\t" - "cmp %3, 0x0\n\t" - "bne,a 1b\n\t" - "add %1, 0x1, %1\n\t" - "2: ldub [%2], %3\n\t" - "stb %3, [%1]\n\t" - "add %1, 0x1, %1\n\t" - "add %3, -1, %3\n\t" - "cmp %3, 0x0\n\t" - "bne 2b\n\t" - "add %2, 0x1, %2\n\t" : - "=r" (retval), "=r" (dest), "=r" (src), "=r" (len), "=r" (temp) : - "0" (retval), "1" (dest), "2" (src), "3" (len), "4" (temp)); - - return retval; + extern void __copy_1page(void *, const void *); + + if(n <= 32) { + __builtin_memcpy(to, from, n); + } else { + switch(n) { + case 4096: + __copy_1page(to, from); + break; + default: + __memcpy(to, from, n); + break; + } + } + return to; } -extern __inline__ char *strchr(const char *src, int c) +extern inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n) { - register char temp=0; - register char *trick=0; - - __asm__("1: ldub [%0], %2\n\t" - "cmp %2, %1\n\t" - "bne,a 1b\n\t" - "add %0, 0x1, %0\n\t" - "or %%g0, %0, %3\n\t" : - "=r" (src), "=r" (c), "=r" (temp), "=r" (trick), "=r" (src) : - "0" (src), "1" (c), "2" (temp), "3" (trick), "4" (src)); - - return trick; + __memcpy(to, from, n); + return to; } -extern __inline__ char *strpbrk(const char *cs, const char *ct) -{ - register char temp1, temp2; - register char *scratch; - register char *trick; - - __asm__("or %%g0, %1, %4\n\t" - "1: ldub [%0], %2\n\t" - "2: ldub [%1], %3\n\t" - "cmp %3, %2\n\t" - "be 3f\n\t" - "nop\n\t" - "cmp %3, 0x0\n\t" - "bne 2b\n\t" - "add %1, 0x1, %1\n\t" - "or %%g0, %4, %1\n\t" - "b 1b\n\t" - "add %0, 0x1, %0\n\t" - "or %%g0, %0, %5\n\t" : - "=r" (cs) : - "r" (ct), "r" (temp1), "r" (temp2), "r" (scratch), "r" (trick=0), - "0" (cs), "1" (ct)); +#undef memcpy +#define memcpy(t, f, n) \ +(__builtin_constant_p(n) ? \ + __constant_memcpy((t),(f),(n)) : \ + __nonconstant_memcpy((t),(f),(n))) - return trick; - -} +#define __HAVE_ARCH_MEMSET +extern void *__memset(void *,int,__kernel_size_t); - -extern __inline__ size_t strspn(const char *s, const char *accept) +extern inline void *__constant_c_and_count_memset(void *s, char c, size_t count) { - register char temp1, temp2; - register char* scratch; - register size_t trick; - - __asm__("or %%g0, %1, %4\n\t" - "1: ldub [%0], %2\n\t" - "2: ldub [%1], %3\n\t" - "cmp %3, 0x0\n\t" - "be 3f\n\t" - "cmp %3, %2" - "bne 2b\n\t" - "add %1, 0x1, %1\n\t" - "add %0, 0x1, %0\n\t" - "b 1b\n\t" - "add %5, 0x1, %5\n\t" - "3: or %%g0, %0, %4\n\t" : - "=r" (s) : - "r" (accept), "r" (temp1), "r" (temp2), - "r" (scratch), "r" (trick=0), "0" (s)); - - return trick; - -} - -extern __inline__ char *strtok(char *s, const char *ct) -{ - static char* old; /* frob this kludge for now */ - register char *tok; - - if (s == (char *) 0) - { - if (old == (char *) 0) - { - return (char *) 0; + extern void *bzero_1page(void *); + extern void *__bzero(void *, size_t); + + if(!c) { + if(count == 4096) + bzero_1page(s); + else + __bzero(s, count); + } else { + __memset(s, c, count); } - else - s = old; - } - - s += strspn(s, ct); - if(*s == '\0') - { - old = (char *) 0; - return (char *) 0; - } - - tok = s; - s = strpbrk(tok, ct); - if (s == (char *) 0) - old = (char *) 0; - else - { - *s = '\0'; - old = s + 1; - } - return tok; -} - - -extern __inline__ void *memset(void *src, int c, size_t count) -{ - register void *retval; - - __asm__("or %%g0, %1, %0\n\t" - "1: add %1, 0x1, %1\n\t" - "2: add %3, -1, %3\n\t" - "cmp %3, -1\n\t" - "bne,a 1b\n\t" - "stb %2, [%1]\n\t" : - "=r" (retval), "=r" (src), "=r" (c), "=r" (count) : - "0" (retval), "1" (src), "2" (c), "3" (count)); - - return retval; + return s; } -extern __inline__ void *memcpy(void *dest, const void *src, size_t count) +extern inline void *__constant_c_memset(void *s, char c, size_t count) { - register void *retval; - register char tmp; + extern void *__bzero(void *, size_t); - __asm__("or %%g0, %1, %0\n\t" - "add %3, -1, %3\n\t" - "cmp %3, -1\n\t" - "be 2f\n\t" - "1: ldub [%2], %4\n\t" - "add %2, 0x1, %2\n\t" - "add %3, -1, %3\n\t" - "cmp %3, -1\n\t" - "stb %4, [%1]\n\t" - "bne 1b\n\t" - "add %1, 0x1, %1\n\t" - "2: " : - "=r" (retval), "=r" (dest), "=r" (src), "=r" (count), "=r" (tmp) : - "0" (retval), "1" (dest), "2" (src), "3" (count), "4" (tmp)); - - return retval; + if(!c) + __bzero(s, count); + else + __memset(s, c, count); + return s; } -extern __inline__ void *memmove(void *dest, const void *src, size_t count) +#undef memset +#define memset(s, c, count) \ +(__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \ + __constant_c_and_count_memset((s), (c), (count)) : \ + __constant_c_memset((s), (c), (count))) \ + : __memset((s), (c), (count))) + +#define __HAVE_ARCH_MEMSCAN + +#undef memscan +#define memscan(__arg0, __char, __arg2) \ +({ \ + extern void *__memscan_zero(void *, size_t); \ + extern void *__memscan_generic(void *, int, size_t); \ + void *__retval, *__addr = (__arg0); \ + size_t __size = (__arg2); \ + \ + if(__builtin_constant_p(__char) && !(__char)) \ + __retval = __memscan_zero(__addr, __size); \ + else \ + __retval = __memscan_generic(__addr, (__char), __size); \ + \ + __retval; \ +}) + +#define __HAVE_ARCH_MEMCMP + +/* Now the str*() stuff... */ +#define __HAVE_ARCH_STRLEN + +#define __HAVE_ARCH_STRNCMP + +extern int __strncmp(const char *, const char *, __kernel_size_t); + +extern inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count) { - register void *retval; - register char tmp; - - __asm__("or %%g0, %1, %1\n\t" - "add %3, -1, %3\n\t" - "cmp %3, -1\n\t" - "be 2f\n\t" - "1: ldub [%2], %4\n\t" - "add %2, 0x1, %2\n\t" - "add %3, -1, %3\n\t" - "cmp %3, -1\n\t" - "stb %4, [%1]\n\t" - "bne 1b\n\t" - "add %1, 0x1, %1\n\t" - "2: " : - "=r" (retval), "=r" (dest), "=r" (src), "=r" (count), "=r" (tmp) : - "0" (retval), "1" (dest), "2" (src), "3" (count), "4" (tmp)); - - return retval; + register int retval; + switch(count) { + case 0: return 0; + case 1: return (src[0] - dest[0]); + case 2: retval = (src[0] - dest[0]); + if(!retval && src[0]) + retval = (src[1] - dest[1]); + return retval; + case 3: retval = (src[0] - dest[0]); + if(!retval && src[0]) { + retval = (src[1] - dest[1]); + if(!retval && src[1]) + retval = (src[2] - dest[2]); + } + return retval; + case 4: retval = (src[0] - dest[0]); + if(!retval && src[0]) { + retval = (src[1] - dest[1]); + if(!retval && src[1]) { + retval = (src[2] - dest[2]); + if (!retval && src[2]) + retval = (src[3] - dest[3]); + } + } + return retval; + case 5: retval = (src[0] - dest[0]); + if(!retval && src[0]) { + retval = (src[1] - dest[1]); + if(!retval && src[1]) { + retval = (src[2] - dest[2]); + if (!retval && src[2]) { + retval = (src[3] - dest[3]); + if (!retval && src[3]) + retval = (src[4] - dest[4]); + } + } + } + return retval; + default: + retval = (src[0] - dest[0]); + if(!retval && src[0]) { + retval = (src[1] - dest[1]); + if(!retval && src[1]) { + retval = (src[2] - dest[2]); + if(!retval && src[2]) + retval = __strncmp(src+3,dest+3,count-3); + } + } + return retval; + } } -extern __inline__ int memcmp(const void *cs, const void *ct, size_t count) -{ - register int retval; - register unsigned long tmp1, tmp2; - - __asm__("or %%g0, %1, %0\n\t" - "cmp %3, 0x0\n\t" - "ble,a 3f\n\t" - "or %%g0, %%g0, %0\n\t" - "1: ldub [%1], %4\n\t" - "ldub [%2], %5\n\t" - "cmp %4, %5\n\t" - "be,a 2f\n\t" - "add %1, 0x1, %1\n\t" - "bgeu 3f\n\t" - "or %%g0, 0x1, %0\n\t" - "b 3f\n\t" - "or %%g0, -1, %0\n\t" - "2: add %3, -1, %3\n\t" - "cmp %3, 0x0\n\t" - "bg 1b\n\t" - "add %2, 0x1, %2\n\t" - "or %%g0, %%g0, %0\n\t" - "3: " : - "=r" (retval) : - "r" (cs), "r" (ct), "r" (count), "r" (tmp1=0), "r" (tmp2=0)); +#undef strncmp +#define strncmp(__arg0, __arg1, __arg2) \ +(__builtin_constant_p(__arg2) ? \ + __constant_strncmp(__arg0, __arg1, __arg2) : \ + __strncmp(__arg0, __arg1, __arg2)) - return retval; -} +#endif /* (__KERNEL__) && !(_KSYMS_INTERNEL) */ +#endif /* !(__SPARC_STRING_H__) */ diff --git a/include/asm-sparc/svr4.h b/include/asm-sparc/svr4.h new file mode 100644 index 000000000..7eb1c3aad --- /dev/null +++ b/include/asm-sparc/svr4.h @@ -0,0 +1,119 @@ +/* Solaris/SPARC constants and definitions -- + * (C) 1996 Miguel de Icaza + * + * This file is not meant to be included by user level applications + * but the solaris syscall emulator + */ + +#ifndef _SPARC_SVR4_H +#define _SPARC_SVR4_H + +/* Signals as used by svr4 */ +typedef struct { /* signal set type */ + ulong sigbits[4]; +} svr4_sigset_t; + +/* Values for siginfo.code */ +#define SVR4_SINOINFO 32767 +/* Siginfo, sucker expects bunch of information on those parameters */ +typedef union { + char total_size [128]; + struct { + int signo; + int code; + int error; + union { + } data; + } siginfo; +} svr4_siginfo_t; + +/* Context definition */ + +/* Location of the user stored registers into a greg_t */ +enum { + SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y, + SVR4_G1, SVR4_G2, SVR4_G3, SVR4_G4, + SVR4_G5, SVR4_G6, SVR4_G7, SVR4_O0, + SVR4_O1, SVR4_O2, SVR4_O3, SVR4_O4, + SVR4_O5, SVR4_O6, SVR4_O7 +}; + +/* sizeof (regs) / sizeof (greg_t), defined in the ABI */ +#define SVR4_NREGS 19 +#define SVR4_MAXWIN 31 + +typedef struct { + uint rwin_lo[8]; + uint rwin_in[8]; +} svr4_rwindow_t; + +typedef struct { + int count; + int *winptr [SVR4_MAXWIN]; /* pointer to the windows */ + svr4_rwindow_t win[SVR4_MAXWIN]; /* the windows */ +} svr4_gwindows_t; + +typedef int svr4_gregset_t[SVR4_NREGS]; + +typedef struct { + double fpu_regs[32]; + void *fp_q; + unsigned fp_fsr; + u_char fp_nqel; + u_char fp_nqsize; + u_char inuse; /* if fpu is in use */ +} svr4_fregset_t; + +typedef struct { + uint id; /* if this holds "xrs" string => ptr is valid */ + caddr_t ptr; +} svr4_xrs_t; + +/* Machine dependant context */ +typedef struct { + svr4_gregset_t greg; /* registers 0..19 (see top) */ + svr4_gwindows_t *gwin; /* may point to register windows */ + svr4_fregset_t freg; /* floating point registers */ + svr4_xrs_t xrs; /* mhm? */ + long pad[19]; +} svr4_mcontext_t; + +/* flags for stack_t.flags */ +enum svr4_stack_flags { + SS_ONSTACK, + SVR4_SS_DISABLE, +}; + +/* signal stack exection place, unsupported */ +typedef struct svr4_stack_t { + char *sp; + int size; + int flags; +} svr4_stack_t; + +/* Context used by getcontext and setcontext */ +typedef struct svr4_ucontext_t { + u_long flags; /* context flags, indicate what is loaded */ + struct svr4_ucontext *link; + svr4_sigset_t sigmask; + svr4_stack_t stack; + svr4_mcontext_t mcontext; + long pad[23]; +} svr4_ucontext_t; + +/* windows hold the windows as they were at signal time, + * ucontext->mcontext holds a pointer to them. + * addresses for uc and si are passed as parameters to svr4 signal + * handler + */ + +/* This is the signal frame that is passed to the signal handler */ +typedef struct { + svr4_gwindows_t gw; /* windows */ + svr4_ucontext_t uc; /* machine context */ + svr4_siginfo_t si; /* siginfo */ +} svr4_signal_frame_t; + +#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7))) + +#endif /* include control */ diff --git a/include/asm-sparc/swift.h b/include/asm-sparc/swift.h new file mode 100644 index 000000000..c3e2ffe2d --- /dev/null +++ b/include/asm-sparc/swift.h @@ -0,0 +1,94 @@ +/* swift.h: Specific definitions for the _broken_ Swift SRMMU + * MMU module. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_SWIFT_H +#define _SPARC_SWIFT_H + +/* Swift is so brain damaged, here is the mmu control register. */ +#define SWIFT_ST 0x00800000 /* SW tablewalk enable */ +#define SWIFT_WP 0x00400000 /* Watchpoint enable */ + +/* Branch folding (buggy, disable on production systems!) */ +#define SWIFT_BF 0x00200000 +#define SWIFT_PMC 0x00180000 /* Page mode control */ +#define SWIFT_PE 0x00040000 /* Parity enable */ +#define SWIFT_PC 0x00020000 /* Parity control */ +#define SWIFT_AP 0x00010000 /* Graphics page mode control (TCX/SX) */ +#define SWIFT_AC 0x00008000 /* Alternate Cacheability (see viking.h) */ +#define SWIFT_BM 0x00004000 /* Boot mode */ +#define SWIFT_RC 0x00003c00 /* DRAM refresh control */ +#define SWIFT_IE 0x00000200 /* Instruction cache enable */ +#define SWIFT_DE 0x00000100 /* Data cache enable */ +#define SWIFT_SA 0x00000080 /* Store Allocate */ +#define SWIFT_NF 0x00000002 /* No fault mode */ +#define SWIFT_EN 0x00000001 /* MMU enable */ + +/* Bits [13:5] select one of 512 instruction cache tags */ +extern __inline__ void swift_inv_insn_tag(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_TXTC_TAG)); +} + +/* Bits [12:4] select one of 512 data cache tags */ +extern __inline__ void swift_inv_data_tag(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_DATAC_TAG)); +} + +extern __inline__ void swift_flush_dcache(void) +{ + unsigned long addr; + + for(addr = 0; addr < 0x2000; addr += 0x10) + swift_inv_data_tag(addr); +} + +extern __inline__ void swift_flush_icache(void) +{ + unsigned long addr; + + for(addr = 0; addr < 0x4000; addr += 0x20) + swift_inv_insn_tag(addr); +} + +extern __inline__ void swift_idflash_clear(void) +{ + unsigned long addr; + + for(addr = 0; addr < 0x2000; addr += 0x10) { + swift_inv_insn_tag(addr<<1); + swift_inv_data_tag(addr); + } +} + +/* Swift is so broken, it isn't even safe to use the following. */ +extern __inline__ void swift_flush_page(unsigned long page) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (page), "i" (ASI_M_FLUSH_PAGE)); +} + +extern __inline__ void swift_flush_segment(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_SEG)); +} + +extern __inline__ void swift_flush_region(unsigned long addr) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_FLUSH_REGION)); +} + +extern __inline__ void swift_flush_context(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_FLUSH_CTX)); +} + +#endif /* !(_SPARC_SWIFT_H) */ diff --git a/include/asm-sparc/sysen.h b/include/asm-sparc/sysen.h index f72b40c67..692fa6f22 100644 --- a/include/asm-sparc/sysen.h +++ b/include/asm-sparc/sysen.h @@ -1,14 +1,15 @@ +/* $Id: sysen.h,v 1.3 1995/11/25 02:32:58 davem Exp $ + * sysen.h: Bit fields within the "System Enable" register accessed via + * the ASI_CONTROL address space at address AC_SYSENABLE. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + #ifndef _SPARC_SYSEN_H #define _SPARC_SYSEN_H -/* sysen.h: Bit fields within the "System Enable" register accessed via - the ASI_CONTROL address space at address AC_SYSENABLE. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ - #define SENABLE_DVMA 0x20 /* enable dvma transfers */ #define SENABLE_CACHE 0x10 /* enable VAC cache */ -#define SENABLE_RESET 0x04 /* reset the whole machine, danger Will Robinson */ +#define SENABLE_RESET 0x04 /* reset whole machine, danger Will Robinson */ #endif /* _SPARC_SYSEN_H */ diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 3c4a62c9a..34800571c 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -1,135 +1,250 @@ +/* $Id: system.h,v 1.42 1996/09/30 02:23:21 davem Exp $ */ #ifndef __SPARC_SYSTEM_H #define __SPARC_SYSTEM_H -#include <asm/segment.h> +#include <linux/kernel.h> -/* - * System defines.. Note that this is included both from .c and .S - * files, so it does only defines, not any C code. - */ - -/* - * I wish the boot time image was as beautiful as the Alpha's - * but no such luck. The icky PROM loads us at 0x0, and jumps - * to magic address 0x4000 to start thing going. This means that - * I can stick the pcb and user/kernel stacks in the area from - * 0x0-0x4000 and be reasonably sure that this is sane. - * - * Sorry, I can't impress people with cool looking 64-bit values - * yet. ;-) - */ +#include <asm/segment.h> -#include <asm/openprom.h> +#ifdef __KERNEL__ +#include <asm/page.h> +#include <asm/oplib.h> #include <asm/psr.h> +#endif -#define INIT_PCB 0x00011fe0 -#define INIT_STACK 0x00013fe0 -#define START_ADDR 0x00004000 -#define START_SIZE (32*1024) -#define EMPTY_PGT 0x00001000 -#define EMPTY_PGE 0x00001000 -#define ZERO_PGE 0x00001000 - -#define IRQ_ENA_ADR 0x2000 /* This is a bitmap of all activated IRQ's - * which is mapped in head.S during boot. - */ +#define EMPTY_PGT (&empty_bad_page) +#define EMPTY_PGE (&empty_bad_page_table) #ifndef __ASSEMBLY__ -extern void wrent(void *, unsigned long); -extern void wrkgp(unsigned long); -extern struct linux_romvec *romvec; +/* + * Sparc (general) CPU types + */ +enum sparc_cpu { + sun4 = 0x00, + sun4c = 0x01, + sun4m = 0x02, + sun4d = 0x03, + sun4e = 0x04, + sun4u = 0x05, /* V8 ploos ploos */ + sun_unknown = 0x06, +}; + +extern enum sparc_cpu sparc_cpu_model; + +extern unsigned long empty_bad_page; +extern unsigned long empty_bad_page_table; +extern unsigned long empty_zero_page; -#define halt() { romvec->pv_halt(); } -#define move_to_user_mode() halt() -#define switch_to(x) halt() +extern struct linux_romvec *romvec; +#define halt() romvec->pv_halt() -#ifndef stbar /* store barrier Sparc insn to synchronize stores in PSO */ -#define stbar() __asm__ __volatile__("stbar": : :"memory") +/* When a context switch happens we must flush all user windows so that + * the windows of the current process are flushed onto its stack. This + * way the windows are all clean for the next process and the stack + * frames are up to date. + */ +extern void flush_user_windows(void); +extern void synchronize_user_stack(void); +extern void fpsave(unsigned long *fpregs, unsigned long *fsr, + void *fpqueue, unsigned long *fpqdepth); + +#ifdef __SMP__ +#define SWITCH_ENTER \ + cli(); \ + if(prev->flags & PF_USEDFPU) { \ + fpsave(&prev->tss.float_regs[0], &prev->tss.fsr, \ + &prev->tss.fpqueue[0], &prev->tss.fpqdepth); \ + prev->flags &= ~PF_USEDFPU; \ + prev->tss.kregs->psr &= ~PSR_EF; \ + } \ + prev->lock_depth = syscall_count; \ + kernel_counter += (next->lock_depth - prev->lock_depth); \ + syscall_count = next->lock_depth; + +#define SWITCH_EXIT sti(); +#define SWITCH_DO_LAZY_FPU +#else +#define SWITCH_ENTER +#define SWITCH_EXIT +#define SWITCH_DO_LAZY_FPU if(last_task_used_math != next) next->tss.kregs->psr&=~PSR_EF; #endif -/* Changing the PIL on the sparc is a bit hairy. I'll figure out some - * more optimized way of doing this soon. This is bletcherous code. + /* Much care has gone into this code, do not touch it. */ +#define switch_to(prev, next) do { \ + __label__ here; \ + register unsigned long task_pc asm("o7"); \ + SWITCH_ENTER \ + SWITCH_DO_LAZY_FPU \ + __asm__ __volatile__( \ + ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \ + "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ + "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ + "save %sp, -0x40, %sp\n\t" \ + "restore; restore; restore; restore; restore; restore; restore"); \ + if(!(next->tss.flags & SPARC_FLAG_KTHREAD) && \ + !(next->flags & PF_EXITING)) \ + switch_to_context(next); \ + task_pc = ((unsigned long) &&here) - 0x8; \ + __asm__ __volatile__( \ + "rd\t%%psr, %%g4\n\t" \ + "std\t%%sp, [%%g6 + %3]\n\t" \ + "rd\t%%wim, %%g5\n\t" \ + "wr\t%%g4, 0x20, %%psr\n\t" \ + "std\t%%g4, [%%g6 + %2]\n\t" \ + "mov\t%1, %%g6\n\t" \ + "ldd\t[%%g6 + %2], %%g4\n\t" \ + "st\t%1, [%0]\n\t" \ + "wr\t%%g4, 0x20, %%psr\n\t" \ + "ldd\t[%%g6 + %3], %%sp\n\t" \ + "wr\t%%g5, 0x0, %%wim\n\t" \ + "ldd\t[%%sp + 0x00], %%l0\n\t" \ + "ldd\t[%%sp + 0x08], %%l2\n\t" \ + "ldd\t[%%sp + 0x10], %%l4\n\t" \ + "ldd\t[%%sp + 0x18], %%l6\n\t" \ + "ldd\t[%%sp + 0x20], %%i0\n\t" \ + "ldd\t[%%sp + 0x28], %%i2\n\t" \ + "ldd\t[%%sp + 0x30], %%i4\n\t" \ + "ldd\t[%%sp + 0x38], %%i6\n\t" \ + "wr\t%%g4, 0x0, %%psr\n\t" \ + "nop\n\t" \ + "jmpl\t%%o7 + 0x8, %%g0\n\t" \ + " nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \ + "r" (task_pc) : "g4", "g5"); \ +here: SWITCH_EXIT } while(0) + +/* Changing the IRQ level on the Sparc. We now avoid writing the psr + * whenever possible. */ +extern __inline__ void setipl(unsigned long __orig_psr) +{ + __asm__ __volatile__("wr\t%0, 0x0, %%psr\n\t" + "nop; nop; nop;" : : "r" (__orig_psr) : "memory"); +} -#define swpipl(__new_ipl) \ -({ unsigned long psr, retval; \ -__asm__ __volatile__( \ - "rd %%psr, %0\n\t" : "=&r" (psr)); \ -retval = psr; \ -psr = (psr & ~(PSR_PIL)); \ -psr |= ((__new_ipl << 8) & PSR_PIL); \ -__asm__ __volatile__( \ - "wr %0, 0x0, %%psr\n\t" \ - : : "r" (psr)); \ -retval = ((retval>>8)&15); \ -retval; }) - -#define cli() swpipl(15) /* 15 = no int's except nmi's */ -#define sti() swpipl(0) /* I'm scared */ -#define save_flags(flags) do { flags = swpipl(15); } while (0) -#define restore_flags(flags) swpipl(flags) - -#define iret() __asm__ __volatile__ ("jmp %%l1\n\t" \ - "rett %%l2\n\t": : :"memory") - -#define _set_gate(gate_addr,type,dpl,addr) \ -__asm__ __volatile__ ("nop\n\t") - -#define set_intr_gate(n,addr) \ - _set_gate(&idt[n],14,0,addr) - -#define set_trap_gate(n,addr) \ - _set_gate(&idt[n],15,0,addr) +extern __inline__ void cli(void) +{ + unsigned long tmp; + + __asm__ __volatile__("rd\t%%psr, %0\n\t" + "andcc\t%0, %1, %%g0\n\t" + "be,a\t1f\n\t" + " wr\t%0, %1, %%psr\n" + "1:\tnop; nop" + : "=r" (tmp) + : "i" (PSR_PIL) + : "memory"); +} -#define set_system_gate(n,addr) \ - _set_gate(&idt[n],15,3,addr) +extern __inline__ void sti(void) +{ + unsigned long tmp; + + __asm__ __volatile__("rd\t%%psr, %0\n\t" + "andcc\t%0, %1, %%g0\n\t" + "bne,a\t1f\n\t" + " wr\t%0, %1, %%psr\n" + "1:\tnop; nop" + : "=r" (tmp) + : "i" (PSR_PIL) + : "memory"); +} -#define set_call_gate(a,addr) \ - _set_gate(a,12,3,addr) +extern __inline__ unsigned long getipl(void) +{ + unsigned long retval; + __asm__ __volatile__("rd\t%%psr, %0" : "=r" (retval)); + return retval; +} -extern inline unsigned int get_psr(void) +extern __inline__ unsigned long swap_pil(unsigned long __new_psr) { - unsigned int ret_val; - __asm__("rd %%psr, %0\n\t" : - "=r" (ret_val)); - return ret_val; + unsigned long retval, tmp1, tmp2; + + __asm__ __volatile__("rd\t%%psr, %0\n\t" + "and\t%0, %4, %1\n\t" + "and\t%3, %4, %2\n\t" + "xorcc\t%1, %2, %%g0\n\t" + "bne,a\t1f\n\t" + " wr %0, %4, %%psr\n" + "1:\tnop; nop" + : "=r" (retval), "=r" (tmp1), "=r" (tmp2) + : "r" (__new_psr), "i" (PSR_PIL) + : "memory"); + return retval; } -extern inline void put_psr(unsigned int new_psr) +extern __inline__ unsigned long read_psr_and_cli(void) { - __asm__("wr %0, 0x0, %%psr\n\t" : : - "r" (new_psr)); + unsigned long retval; + + __asm__ __volatile__("rd\t%%psr, %0\n\t" + "andcc\t%0, %1, %%g0\n\t" + "be,a\t1f\n\t" + " wr\t%0, %1, %%psr\n" + "1:\tnop; nop" + : "=r" (retval) + : "i" (PSR_PIL) + : "memory"); + return retval; } -/* Must this be atomic? */ +extern char spdeb_buf[256]; -extern inline void *xchg_u32(int * m, unsigned long val) -{ - unsigned long dummy; - - __asm__ __volatile__( - "ld %1,%2 ! xchg_u32() is here\n\t" - "st %0, %1\n\t" - "or %%g0, %2, %0" - : "=r" (val), "=m" (*m), "=r" (dummy) - : "0" (val)); - return (void *) val; -} +#define save_flags(flags) ((flags) = getipl()) +#define save_and_cli(flags) ((flags) = read_psr_and_cli()) +#define restore_flags(flags) setipl((flags)) +/* XXX Change this if we ever use a PSO mode kernel. */ +#define mb() __asm__ __volatile__ ("" : : : "memory") -/* pointers are 32 bits on the sparc (at least the v8, and they'll work - * on the V9 none the less). I don't need the xchg_u64 routine for now. - */ +#define nop() __asm__ __volatile__ ("nop"); -extern inline void *xchg_ptr(void *m, void *val) +extern __inline__ unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) { - return (void *) xchg_u32((int *) m, (unsigned long) val); + __asm__ __volatile__(" + rd %%psr, %%g3 + andcc %%g3, %3, %%g0 + be,a 1f + wr %%g3, %3, %%psr +1: ld [%1], %%g2 + andcc %%g3, %3, %%g0 + st %2, [%1] + be,a 1f + wr %%g3, 0x0, %%psr +1: nop + mov %%g2, %0 + " + : "=&r" (val) + : "r" (m), "0" (val), "i" (PSR_PIL) + : "g2", "g3"); + + return val; } +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) +#define tas(ptr) (xchg((ptr),1)) + +extern void __xchg_called_with_bad_pointer(void); +static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size) +{ + switch (size) { + case 4: + return xchg_u32(ptr, x); + }; + __xchg_called_with_bad_pointer(); + return x; +} #endif /* __ASSEMBLY__ */ -#endif +/* + * Reset the machine. + */ +extern void hard_reset_now(void); + +#endif /* !(__SPARC_SYSTEM_H) */ diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h new file mode 100644 index 000000000..9a078c619 --- /dev/null +++ b/include/asm-sparc/termbits.h @@ -0,0 +1,208 @@ +#ifndef _SPARC_TERMBITS_H +#define _SPARC_TERMBITS_H + +#include <linux/posix_types.h> + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned long tcflag_t; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +#define NCCS 17 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ +#ifdef __KERNEL__ +#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t)) + cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ +#endif +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VEOL 5 +#define VEOL2 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 + + + +#define VSUSP 10 +#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */ +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 + +/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is + * shared with eof/eol + */ +#ifdef __KERNEL__ +#define VMIN 16 +#define VTIME 17 +#else +#define VMIN VEOF +#define VTIME VEOL +#endif + +/* c_iflag bits */ +#define IGNBRK 0x00000001 +#define BRKINT 0x00000002 +#define IGNPAR 0x00000004 +#define PARMRK 0x00000008 +#define INPCK 0x00000010 +#define ISTRIP 0x00000020 +#define INLCR 0x00000040 +#define IGNCR 0x00000080 +#define ICRNL 0x00000100 +#define IUCLC 0x00000200 +#define IXON 0x00000400 +#define IXANY 0x00000800 +#define IXOFF 0x00001000 +#define IMAXBEL 0x00002000 + +/* c_oflag bits */ +#define OPOST 0x00000001 +#define OLCUC 0x00000002 +#define ONLCR 0x00000004 +#define OCRNL 0x00000008 +#define ONOCR 0x00000010 +#define ONLRET 0x00000020 +#define OFILL 0x00000040 +#define OFDEL 0x00000080 +#define NLDLY 0x00000100 +#define NL0 0x00000000 +#define NL1 0x00000100 +#define CRDLY 0x00000600 +#define CR0 0x00000000 +#define CR1 0x00000200 +#define CR2 0x00000400 +#define CR3 0x00000600 +#define TABDLY 0x00001800 +#define TAB0 0x00000000 +#define TAB1 0x00000800 +#define TAB2 0x00001000 +#define TAB3 0x00001800 +#define XTABS 0x00001800 +#define BSDLY 0x00002000 +#define BS0 0x00000000 +#define BS1 0x00002000 +#define VTDLY 0x00004000 +#define VT0 0x00000000 +#define VT1 0x00004000 +#define FFDLY 0x00008000 +#define FF0 0x00000000 +#define FF1 0x00008000 +#define PAGEOUT 0x00010000 /* SUNOS specific */ +#define WRAP 0x00020000 /* SUNOS specific */ + +/* c_cflag bit meaning */ +#define CBAUD 0x0000000f +#define B0 0x00000000 /* hang up */ +#define B50 0x00000001 +#define B75 0x00000002 +#define B110 0x00000003 +#define B134 0x00000004 +#define B150 0x00000005 +#define B200 0x00000006 +#define B300 0x00000007 +#define B600 0x00000008 +#define B1200 0x00000009 +#define B1800 0x0000000a +#define B2400 0x0000000b +#define B4800 0x0000000c +#define B9600 0x0000000d +#define B19200 0x0000000e +#define B38400 0x0000000f +#define EXTA B19200 +#define EXTB B38400 +#define CSIZE 0x00000030 +#define CS5 0x00000000 +#define CS6 0x00000010 +#define CS7 0x00000020 +#define CS8 0x00000030 +#define CSTOPB 0x00000040 +#define CREAD 0x00000080 +#define PARENB 0x00000100 +#define PARODD 0x00000200 +#define HUPCL 0x00000400 +#define CLOCAL 0x00000800 +/* We'll never see these speeds with the Zilogs' but for completeness... */ +#define CBAUDEX 0x00010000 +#define B57600 0x00010001 +#define B115200 0x00010002 +#define B230400 0x00010003 +#define B460800 0x00010004 +#define CIBAUD 0x000f0000 /* input baud rate (not used) */ +#define CRTSCTS 0x80000000 /* flow control */ + +/* c_lflag bits */ +#define ISIG 0x00000001 +#define ICANON 0x00000002 +#define XCASE 0x00000004 +#define ECHO 0x00000008 +#define ECHOE 0x00000010 +#define ECHOK 0x00000020 +#define ECHONL 0x00000040 +#define NOFLSH 0x00000080 +#define TOSTOP 0x00000100 +#define ECHOCTL 0x00000200 +#define ECHOPRT 0x00000400 +#define ECHOKE 0x00000800 +#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */ +#define FLUSHO 0x00002000 +#define PENDIN 0x00004000 +#define IEXTEN 0x00008000 + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* !(_SPARC_TERMBITS_H) */ diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h new file mode 100644 index 000000000..e2991ecf7 --- /dev/null +++ b/include/asm-sparc/termios.h @@ -0,0 +1,168 @@ +/* $Id: termios.h,v 1.20 1996/10/31 00:59:54 davem Exp $ */ +#ifndef _SPARC_TERMIOS_H +#define _SPARC_TERMIOS_H + +#include <asm/ioctls.h> +#include <asm/termbits.h> + +#if defined(__KERNEL__) || defined(__DEFINE_BSD_TERMIOS) +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; +#endif /* __KERNEL__ */ + +struct sunos_ttysize { + int st_lines; /* Lines on the terminal */ + int st_columns; /* Columns on the terminal */ +}; + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 + +#ifdef __KERNEL__ + +/* + * c_cc characters in the termio structure. Oh, how I love being + * backwardly compatible. Notice that character 4 and 5 are + * interpreted differently depending on whether ICANON is set in + * c_lflag. If it's set, they are used as _VEOF and _VEOL, otherwise + * as _VMIN and V_TIME. This is for compatibility with OSF/1 (which + * is compatible with sysV)... + */ +#define _VMIN 4 +#define _VTIME 5 + + +#include <linux/string.h> + +/* intr=^C quit=^\ erase=del kill=^U + eof=^D eol=\0 eol2=\0 sxtc=\0 + start=^Q stop=^S susp=^Z dsusp=^Y + reprint=^R discard=^U werase=^W lnext=^V + vmin=\1 vtime=\0 +*/ +#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000" + +/* + * Translate a "termio" structure into a "termios". Ugh. + */ +extern __inline__ void trans_from_termio(struct termio * termio, + struct termios * termios) +{ +#define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y)) + SET_LOW_BITS(termios->c_iflag, termio->c_iflag); + SET_LOW_BITS(termios->c_oflag, termio->c_oflag); + SET_LOW_BITS(termios->c_cflag, termio->c_cflag); + SET_LOW_BITS(termios->c_lflag, termio->c_lflag); +#undef SET_LOW_BITS + memcpy (termios->c_cc, termio->c_cc, NCC); +} + +/* + * Translate a "termios" structure into a "termio". Ugh. + * + * Note the "fun" _VMIN overloading. + */ +extern __inline__ void trans_to_termio(struct termios * termios, + struct termio * termio) +{ + termio->c_iflag = termios->c_iflag; + termio->c_oflag = termios->c_oflag; + termio->c_cflag = termios->c_cflag; + termio->c_lflag = termios->c_lflag; + termio->c_line = termios->c_line; + memcpy(termio->c_cc, termios->c_cc, NCC); + if (!(termios->c_lflag & ICANON)) { + termio->c_cc[_VMIN] = termios->c_cc[VMIN]; + termio->c_cc[_VTIME] = termios->c_cc[VTIME]; + } +} + +/* Note that in this case DEST is a user buffer and thus the checking + * and this ugly macro to avoid header file problems. + */ +#define termios_to_userland(d, s) \ +do { \ + struct termios *dest = (d); \ + struct termios *source = (s); \ + put_user(source->c_iflag, &dest->c_iflag); \ + put_user(source->c_oflag, &dest->c_oflag); \ + put_user(source->c_cflag, &dest->c_cflag); \ + put_user(source->c_lflag, &dest->c_lflag); \ + put_user(source->c_line, &dest->c_line); \ + copy_to_user(dest->c_cc, source->c_cc, NCCS); \ + if (!(source->c_lflag & ICANON)){ \ + put_user(source->c_cc[VMIN], &dest->c_cc[_VMIN]); \ + put_user(source->c_cc[VTIME], &dest->c_cc[_VTIME]); \ + } else { \ + put_user(source->c_cc[VEOF], &dest->c_cc[VEOF]); \ + put_user(source->c_cc[VEOL], &dest->c_cc[VEOL]); \ + } \ +} while(0) + +/* termios to termios handling SunOS overloading of eof,eol/vmin,vtime + * In this case we are only working with kernel buffers so direct + * accesses are ok. + */ +extern __inline__ void termios_from_userland(struct termios * source, + struct termios * dest) +{ + dest->c_iflag = source->c_iflag; + dest->c_oflag = source->c_oflag; + dest->c_cflag = source->c_cflag; + dest->c_lflag = source->c_lflag; + dest->c_line = source->c_line; + memcpy(dest->c_cc, source->c_cc, NCCS); + if (dest->c_lflag & ICANON){ + dest->c_cc [VEOF] = source->c_cc [VEOF]; + dest->c_cc [VEOL] = source->c_cc [VEOL]; + } else { + dest->c_cc[VMIN] = source->c_cc[_VMIN]; + dest->c_cc[VTIME] = source->c_cc[_VTIME]; + } +} + +#endif /* __KERNEL__ */ + +#endif /* _SPARC_TERMIOS_H */ diff --git a/include/asm-sparc/timer.h b/include/asm-sparc/timer.h new file mode 100644 index 000000000..3820794e7 --- /dev/null +++ b/include/asm-sparc/timer.h @@ -0,0 +1,82 @@ +/* $Id: timer.h,v 1.13 1996/08/29 09:48:59 davem Exp $ + * timer.h: Definitions for the timer chips on the Sparc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_TIMER_H +#define _SPARC_TIMER_H + +#include <asm/system.h> /* For NCPUS */ + +/* Timer structures. The interrupt timer has two properties which + * are the counter (which is handled in do_timer in sched.c) and the limit. + * This limit is where the timer's counter 'wraps' around. Oddly enough, + * the sun4c timer when it hits the limit wraps back to 1 and not zero + * thus when calculating the value at which it will fire a microsecond you + * must adjust by one. Thanks SUN for designing such great hardware ;( + */ + +/* Note that I am only going to use the timer that interrupts at + * Sparc IRQ 10. There is another one available that can fire at + * IRQ 14. Currently it is left untouched, we keep the PROM's limit + * register value and let the prom take these interrupts. This allows + * L1-A to work. + */ + +struct sun4c_timer_info { + __volatile__ unsigned int cur_count10; + __volatile__ unsigned int timer_limit10; + __volatile__ unsigned int cur_count14; + __volatile__ unsigned int timer_limit14; +}; + +#define SUN4C_TIMER_PHYSADDR 0xf3000000 + +/* A sun4m has two blocks of registers which are probably of the same + * structure. LSI Logic's L64851 is told to _decrement_ from the limit + * value. Aurora behaves similarly but its limit value is compacted in + * other fashion (it's wider). Documented fields are defined here. + */ + +/* As with the interrupt register, we have two classes of timer registers + * which are per-cpu and master. Per-cpu timers only hit that cpu and are + * only level 14 ticks, master timer hits all cpus and is level 10. + */ + +#define SUN4M_PRM_CNT_L 0x80000000 +#define SUN4M_PRM_CNT_LVALUE 0x7FFFFC00 + +struct sun4m_timer_percpu_info { + __volatile__ unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */ + __volatile__ unsigned int l14_cur_count; + + /* This register appears to be write only and/or inaccessible + * on Uni-Processor sun4m machines. + */ + __volatile__ unsigned int l14_limit_noclear; /* Data access error is here */ + + __volatile__ unsigned int cntrl; /* =1 after POST on Aurora */ + __volatile__ unsigned char space[PAGE_SIZE - 16]; +}; + +struct sun4m_timer_regs { + struct sun4m_timer_percpu_info cpu_timers[NCPUS]; + volatile unsigned int l10_timer_limit; + volatile unsigned int l10_cur_count; + + /* Again, this appears to be write only and/or inaccessible + * on uni-processor sun4m machines. + */ + volatile unsigned int l10_limit_noclear; + + /* This register too, it must be magic. */ + volatile unsigned int foobar; + + volatile unsigned int cfg; /* equals zero at boot time... */ +}; + +extern struct sun4m_timer_regs *sun4m_timers; +extern __volatile__ unsigned int *master_l10_counter; +extern __volatile__ unsigned int *master_l10_limit; + +#endif /* !(_SPARC_TIMER_H) */ diff --git a/include/asm-sparc/traps.h b/include/asm-sparc/traps.h new file mode 100644 index 000000000..3a3940df2 --- /dev/null +++ b/include/asm-sparc/traps.h @@ -0,0 +1,159 @@ +/* $Id: traps.h,v 1.8 1996/05/17 10:38:53 davem Exp $ + * traps.h: Format of entries for the Sparc trap table. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_TRAPS_H +#define _SPARC_TRAPS_H + +#define NUM_SPARC_TRAPS 255 + +#ifndef __ASSEMBLY__ + +/* This is for V8 and V9 compliant Sparc CPUS */ +struct tt_entry { + unsigned long inst_one; + unsigned long inst_two; + unsigned long inst_three; + unsigned long inst_four; +}; + +/* We set this to _start in system setup. */ +extern struct tt_entry *sparc_ttable; + +/* This for V9 compliant Sparc CPUS */ +struct tt_v9_entry { + unsigned long inst_one; + unsigned long inst_two; + unsigned long inst_three; + unsigned long inst_four; + unsigned long inst_five; + unsigned long inst_six; + unsigned long inst_seven; + unsigned long inst_eight; +}; + +/* V9 has multiple trap tables, which one is used depends + * upon how deep within multiple traps you are. + * I believe the UltraSparc supports two levels now. + */ +extern struct tt_v9_entry *sparc_v9_ttablel0; +extern struct tt_v9_entry *sparc_v9_ttablel1; + +extern __inline__ unsigned long get_tbr(void) +{ + unsigned long tbr; + + __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr)); + return tbr; +} + +#endif /* !(__ASSEMBLY__) */ + +/* For patching the trap table at boot time, we need to know how to + * form various common Sparc instructions. Thus these macros... + */ + +#define SPARC_MOV_CONST_L3(const) (0xa6102000 | (const&0xfff)) + +/* The following assumes that the branch lies before the place we + * are branching to. This is the case for a trap vector... + * You have been warned. + */ +#define SPARC_BRANCH(dest_addr, inst_addr) \ + (0x10800000 | (((dest_addr-inst_addr)>>2)&0x3fffff)) + +#define SPARC_RD_PSR_L0 (0xa1480000) +#define SPARC_RD_WIM_L3 (0xa7500000) +#define SPARC_NOP (0x01000000) + +/* Various interesting trap levels. */ +/* First, hardware traps. */ +#define SP_TRAP_TFLT 0x1 /* Text fault */ +#define SP_TRAP_II 0x2 /* Illegal Instruction */ +#define SP_TRAP_PI 0x3 /* Privileged Instruction */ +#define SP_TRAP_FPD 0x4 /* Floating Point Disabled */ +#define SP_TRAP_WOVF 0x5 /* Window Overflow */ +#define SP_TRAP_WUNF 0x6 /* Window Underflow */ +#define SP_TRAP_MNA 0x7 /* Memory Address Unaligned */ +#define SP_TRAP_FPE 0x8 /* Floating Point Exception */ +#define SP_TRAP_DFLT 0x9 /* Data Fault */ +#define SP_TRAP_TOF 0xa /* Tag Overflow */ +#define SP_TRAP_WDOG 0xb /* Watchpoint Detected */ +#define SP_TRAP_IRQ1 0x11 /* IRQ level 1 */ +#define SP_TRAP_IRQ2 0x12 /* IRQ level 2 */ +#define SP_TRAP_IRQ3 0x13 /* IRQ level 3 */ +#define SP_TRAP_IRQ4 0x14 /* IRQ level 4 */ +#define SP_TRAP_IRQ5 0x15 /* IRQ level 5 */ +#define SP_TRAP_IRQ6 0x16 /* IRQ level 6 */ +#define SP_TRAP_IRQ7 0x17 /* IRQ level 7 */ +#define SP_TRAP_IRQ8 0x18 /* IRQ level 8 */ +#define SP_TRAP_IRQ9 0x19 /* IRQ level 9 */ +#define SP_TRAP_IRQ10 0x1a /* IRQ level 10 */ +#define SP_TRAP_IRQ11 0x1b /* IRQ level 11 */ +#define SP_TRAP_IRQ12 0x1c /* IRQ level 12 */ +#define SP_TRAP_IRQ13 0x1d /* IRQ level 13 */ +#define SP_TRAP_IRQ14 0x1e /* IRQ level 14 */ +#define SP_TRAP_IRQ15 0x1f /* IRQ level 15 Non-maskable */ +#define SP_TRAP_RACC 0x20 /* Register Access Error ??? */ +#define SP_TRAP_IACC 0x21 /* Instruction Access Error */ +#define SP_TRAP_CPDIS 0x24 /* Co-Processor Disabled */ +#define SP_TRAP_BADFL 0x25 /* Unimplemented Flush Instruction */ +#define SP_TRAP_CPEXP 0x28 /* Co-Processor Exception */ +#define SP_TRAP_DACC 0x29 /* Data Access Error */ +#define SP_TRAP_DIVZ 0x2a /* Divide By Zero */ +#define SP_TRAP_DSTORE 0x2b /* Data Store Error ??? */ +#define SP_TRAP_DMM 0x2c /* Data Access MMU Miss ??? */ +#define SP_TRAP_IMM 0x3c /* Instruction Access MMU Miss ??? */ + +/* Now the Software Traps... */ +#define SP_TRAP_SUNOS 0x80 /* SunOS System Call */ +#define SP_TRAP_SBPT 0x81 /* Software Breakpoint */ +#define SP_TRAP_SDIVZ 0x82 /* Software Divide-by-Zero trap */ +#define SP_TRAP_FWIN 0x83 /* Flush Windows */ +#define SP_TRAP_CWIN 0x84 /* Clean Windows */ +#define SP_TRAP_RCHK 0x85 /* Range Check */ +#define SP_TRAP_FUNA 0x86 /* Fix Unaligned Access */ +#define SP_TRAP_IOWFL 0x87 /* Integer Overflow */ +#define SP_TRAP_SOLARIS 0x88 /* Solaris System Call */ +#define SP_TRAP_NETBSD 0x89 /* NetBSD System Call */ +#define SP_TRAP_LINUX 0x90 /* Linux System Call */ + +/* Names used for compatibility with SunOS */ +#define ST_SYSCALL 0x00 +#define ST_BREAKPOINT 0x01 +#define ST_DIV0 0x02 +#define ST_FLUSH_WINDOWS 0x03 +#define ST_CLEAN_WINDOWS 0x04 +#define ST_RANGE_CHECK 0x05 +#define ST_FIX_ALIGN 0x06 +#define ST_INT_OVERFLOW 0x07 + +/* Special traps... */ +#define SP_TRAP_KBPT1 0xfe /* KADB/PROM Breakpoint one */ +#define SP_TRAP_KBPT2 0xff /* KADB/PROM Breakpoint two */ + +/* Handy Macros */ +/* Is this a trap we never expect to get? */ +#define BAD_TRAP_P(level) \ + ((level > SP_TRAP_WDOG && level < SP_TRAP_IRQ1) || \ + (level > SP_TRAP_IACC && level < SP_TRAP_CPDIS) || \ + (level > SP_TRAP_BADFL && level < SP_TRAP_CPEXP) || \ + (level > SP_TRAP_DMM && level < SP_TRAP_IMM) || \ + (level > SP_TRAP_IMM && level < SP_TRAP_SUNOS) || \ + (level > SP_TRAP_LINUX && level < SP_TRAP_KBPT1)) + +/* Is this a Hardware trap? */ +#define HW_TRAP_P(level) ((level > 0) && (level < SP_TRAP_SUNOS)) + +/* Is this a Software trap? */ +#define SW_TRAP_P(level) ((level >= SP_TRAP_SUNOS) && (level <= SP_TRAP_KBPT2)) + +/* Is this a system call for some OS we know about? */ +#define SCALL_TRAP_P(level) ((level == SP_TRAP_SUNOS) || \ + (level == SP_TRAP_SOLARIS) || \ + (level == SP_TRAP_NETBSD) || \ + (level == SP_TRAP_LINUX)) + +#endif /* !(_SPARC_TRAPS_H) */ diff --git a/include/asm-sparc/tsunami.h b/include/asm-sparc/tsunami.h new file mode 100644 index 000000000..384ea6e68 --- /dev/null +++ b/include/asm-sparc/tsunami.h @@ -0,0 +1,60 @@ +/* $Id: tsunami.h,v 1.5 1996/08/29 09:49:03 davem Exp $ + * tsunami.h: Module specific definitions for Tsunami V8 Sparcs + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_TSUNAMI_H +#define _SPARC_TSUNAMI_H + +#include <asm/asi.h> + +/* The MMU control register on the Tsunami: + * + * ----------------------------------------------------------------------- + * | implvers |SW|AV|DV|MV| RSV |PC|ITD|ALC| RSV |PE| RC |IE|DE|RSV|NF|ME| + * ----------------------------------------------------------------------- + * 31 24 23 22 21 20 19-18 17 16 14 13-12 11 10-9 8 7 6-2 1 0 + * + * SW: Enable Software Table Walks 0=off 1=on + * AV: Address View bit + * DV: Data View bit + * MV: Memory View bit + * PC: Parity Control + * ITD: ITBR disable + * ALC: Alternate Cacheable + * PE: Parity Enable 0=off 1=on + * RC: Refresh Control + * IE: Instruction cache Enable 0=off 1=on + * DE: Data cache Enable 0=off 1=on + * NF: No Fault, same as all other SRMMUs + * ME: MMU Enable, same as all other SRMMUs + */ + +#define TSUNAMI_SW 0x00800000 +#define TSUNAMI_AV 0x00400000 +#define TSUNAMI_DV 0x00200000 +#define TSUNAMI_MV 0x00100000 +#define TSUNAMI_PC 0x00020000 +#define TSUNAMI_ITD 0x00010000 +#define TSUNAMI_ALC 0x00008000 +#define TSUNAMI_PE 0x00001000 +#define TSUNAMI_RCMASK 0x00000C00 +#define TSUNAMI_IENAB 0x00000200 +#define TSUNAMI_DENAB 0x00000100 +#define TSUNAMI_NF 0x00000002 +#define TSUNAMI_ME 0x00000001 + +extern __inline__ void tsunami_flush_icache(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_IC_FLCLEAR) : "memory"); +} + +extern __inline__ void tsunami_flush_dcache(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_DC_FLCLEAR) : "memory"); +} + +#endif /* !(_SPARC_TSUNAMI_H) */ diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h index c7b65be7a..d8334325a 100644 --- a/include/asm-sparc/types.h +++ b/include/asm-sparc/types.h @@ -1,62 +1,46 @@ +/* $Id: types.h,v 1.10 1996/08/29 09:49:04 davem Exp $ */ #ifndef _SPARC_TYPES_H #define _SPARC_TYPES_H /* * _xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space <-- Linus sez this + * header files exported to user space. */ -/* NOTE: I will have to change these when the V9 sparcs come into play, - * however this won't be for a while. +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. */ -#ifndef _SIZE_T -#define _SIZE_T -#ifdef __svr4__ -typedef unsigned int size_t; /* solaris sucks */ -#else -typedef long unsigned int size_t; /* sunos is much better */ -#endif /* !(__svr4__) */ -#endif - -#ifndef _SSIZE_T -#define _SSIZE_T -typedef int ssize_t; -#endif - -#ifndef _PTRDIFF_T -#define _PTRDIFF_T -typedef int ptrdiff_t; -#endif +typedef unsigned short umode_t; -typedef signed char __s8; +typedef __signed__ char __s8; typedef unsigned char __u8; -typedef signed short __s16; +typedef __signed__ short __s16; typedef unsigned short __u16; -typedef signed int __s32; +typedef __signed__ int __s32; typedef unsigned int __u32; -/* Only 32-bit sparcs for now so.... */ - -typedef signed long long __s64; +typedef __signed__ long long __s64; typedef unsigned long long __u64; #ifdef __KERNEL__ -typedef signed char s8; +typedef __signed__ char s8; typedef unsigned char u8; -typedef signed short s16; +typedef __signed__ short s16; typedef unsigned short u16; -typedef signed int s32; +typedef __signed__ int s32; typedef unsigned int u32; -/* Again, only have to worry about 32-bits */ - -typedef signed long long s64; +typedef __signed__ long long s64; typedef unsigned long long u64; #endif /* __KERNEL__ */ diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h new file mode 100644 index 000000000..53eb75cae --- /dev/null +++ b/include/asm-sparc/uaccess.h @@ -0,0 +1,261 @@ +/* $Id: uaccess.h,v 1.2 1996/10/31 00:59:56 davem Exp $ */ +#ifndef _ASM_UACCESS_H +#define _ASM_UACCESS_H + +/* + * User space memory access functions + */ + +#ifdef __KERNEL__ +#include <linux/sched.h> +#include <linux/string.h> +#include <asm/vac-ops.h> +#endif + +#ifndef __ASSEMBLY__ + +/* Sparc is not segmented, however we need to be able to fool verify_area() + * when doing system calls from kernel mode legitimately. + * + * "For historical reasons, these macros are grossly misnamed." -Linus + */ +#define KERNEL_DS 0 +#define USER_DS 1 + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +#define get_fs() (current->tss.current_ds) +#define get_ds() (KERNEL_DS) +#define set_fs(val) ((current->tss.current_ds) = (val)) + +#define __user_ok(addr,size) (((size) <= page_offset)&&((addr) <= page_offset-(size))) +#define __kernel_ok (get_fs() == KERNEL_DS) +#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) +#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) + +extern inline int verify_area(int type, const void * addr, unsigned long size) +{ + return access_ok(type,addr,size)?0:-EFAULT; +} + +/* Uh, these should become the main single-value transfer routines.. + * They automatically use the right size if we just have the right + * pointer type.. + * + * This gets kind of ugly. We want to return _two_ values in "get_user()" + * and yet we don't want to do any pointers, because that is too much + * of a performance impact. Thus we have a few rather ugly macros here, + * and hide all the uglyness from the user. + */ +#define put_user(x,ptr) ({ \ +unsigned long __pu_addr = (unsigned long)(ptr); \ +__put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); }) + +#define get_user(x,ptr) ({ \ +unsigned long __gu_addr = (unsigned long)(ptr); \ +__get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); }) + +/* + * The "__xxx" versions do not do address space checking, useful when + * doing multiple accesses to the same area (the user has to do the + * checks by hand with "access_ok()") + */ +#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr))) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) ((struct __large_struct *)(x)) + +#define __put_user_check(x,addr,size) ({ \ +register int __pu_ret asm("g1"); \ +__pu_ret = -EFAULT; \ +if (__access_ok(addr,size)) { \ +switch (size) { \ +case 1: __put_user_8(x,addr,__pu_ret); break; \ +case 2: __put_user_16(x,addr,__pu_ret); break; \ +case 4: __put_user_32(x,addr,__pu_ret); break; \ +default: __pu_ret = __put_user_bad(); break; \ +} } __pu_ret; }) + +#define __put_user_nocheck(x,addr,size) ({ \ +register int __pu_ret asm("g1"); \ +__pu_ret = -EFAULT; \ +switch (size) { \ +case 1: __put_user_8(x,addr,__pu_ret); break; \ +case 2: __put_user_16(x,addr,__pu_ret); break; \ +case 4: __put_user_32(x,addr,__pu_ret); break; \ +default: __pu_ret = __put_user_bad(); break; \ +} __pu_ret; }) + +#define __put_user_8(x,addr,ret) \ +__asm__ __volatile( \ + "/* Put user 8, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "stb %1, [%2]\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret) : "r" (x), "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +#define __put_user_16(x,addr,ret) \ +__asm__ __volatile( \ + "/* Put user 16, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "sth %1, [%2]\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret) : "r" (x), "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +#define __put_user_32(x,addr,ret) \ +__asm__ __volatile( \ + "/* Put user 32, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "st %1, [%2]\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret) : "r" (x), "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +extern int __put_user_bad(void); + +#define __get_user_check(x,addr,size,type) ({ \ +register int __gu_ret asm("g1"); \ +register unsigned long __gu_val = 0; \ +__gu_ret = -EFAULT; \ +if (__access_ok(addr,size)) { \ +switch (size) { \ +case 1: __get_user_8(__gu_val,addr,__gu_ret); break; \ +case 2: __get_user_16(__gu_val,addr,__gu_ret); break; \ +case 4: __get_user_32(__gu_val,addr,__gu_ret); break; \ +default: __gu_ret = __get_user_bad(); break; \ +} } x = (type) __gu_val; __gu_ret; }) + +#define __get_user_nocheck(x,addr,size,type) ({ \ +register int __gu_ret asm("g1"); \ +register unsigned long __gu_val = 0; \ +__gu_ret = -EFAULT; \ +switch (size) { \ +case 1: __get_user_8(__gu_val,addr,__gu_ret); break; \ +case 2: __get_user_16(__gu_val,addr,__gu_ret); break; \ +case 4: __get_user_32(__gu_val,addr,__gu_ret); break; \ +default: __gu_ret = __get_user_bad(); break; \ +} x = (type) __gu_val; __gu_ret; }) + +#define __get_user_8(x,addr,ret) \ +__asm__ __volatile__( \ + "/* Get user 8, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "ldub [%2], %1\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret), "=&r" (x) : "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +#define __get_user_16(x,addr,ret) \ +__asm__ __volatile__( \ + "/* Get user 16, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "lduh [%2], %1\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret), "=&r" (x) : "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +#define __get_user_32(x,addr,ret) \ +__asm__ __volatile__( \ + "/* Get user 32, inline. */\n\t" \ + "ld [%%g6 + %3], %%g2\n\t" \ + "set 1f, %0\n\t" \ + "add %%g2, 1, %%g3\n\t" \ + "st %0, [%%g6 + %4]\n\t" \ + "st %%g3, [%%g6 + %3]\n\t" \ + "ld [%2], %1\n\t" \ + "mov 0, %0\n\t" \ + "st %%g2, [%%g6 + %3]\n" \ +"1:\n" : "=&r" (ret), "=&r" (x) : "r" (__m(addr)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.count)), \ + "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ex.expc)) \ + : "g2", "g3") + +extern int __get_user_bad(void); + +extern int __copy_to_user(unsigned long to, unsigned long from, int size); +extern int __copy_from_user(unsigned long to, unsigned long from, int size); + +#define copy_to_user(to,from,n) ({ \ +unsigned long __copy_to = (unsigned long) (to); \ +unsigned long __copy_size = (unsigned long) (n); \ +unsigned long __copy_res; \ +if(__copy_size && __access_ok(__copy_to, __copy_size)) { \ +__copy_res = __copy_to_user(__copy_to, (unsigned long) (from), __copy_size); \ +if(__copy_res) __copy_res = __copy_size - __copy_res; \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +#define copy_from_user(to,from,n) ({ \ +unsigned long __copy_from = (unsigned long) (from); \ +unsigned long __copy_size = (unsigned long) (n); \ +unsigned long __copy_res; \ +if(__copy_size && __access_ok(__copy_from, __copy_size)) { \ +__copy_res = __copy_from_user((unsigned long) (to), __copy_from, __copy_size); \ +if(__copy_res) __copy_res = __copy_size - __copy_res; \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +extern int __clear_user(unsigned long addr, int size); + +#define clear_user(addr,n) ({ \ +unsigned long __clear_addr = (unsigned long) (addr); \ +int __clear_size = (int) (n); \ +int __clear_res; \ +if(__clear_size && __access_ok(__clear_addr, __clear_size)) { \ +__clear_res = __clear_user(__clear_addr, __clear_size); \ +if(__clear_res) __clear_res = __clear_size - __clear_res; \ +} else __clear_res = __clear_size; \ +__clear_res; }) + +extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count); + +#define strncpy_from_user(dest,src,count) ({ \ +unsigned long __sfu_src = (unsigned long) (src); \ +int __sfu_count = (int) (count); \ +long __sfu_res = -EFAULT; \ +if(__access_ok(__sfu_src, __sfu_count)) { \ +__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ +} __sfu_res; }) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_UACCESS_H */ diff --git a/include/asm-sparc/ultra.h b/include/asm-sparc/ultra.h new file mode 100644 index 000000000..fdc6c7f48 --- /dev/null +++ b/include/asm-sparc/ultra.h @@ -0,0 +1,52 @@ +/* $Id: ultra.h,v 1.2 1995/11/25 02:33:10 davem Exp $ + * ultra.h: Definitions and defines for the TI V9 UltraSparc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_ULTRA_H +#define _SPARC_ULTRA_H + +/* Spitfire MMU control register: + * + * ---------------------------------------------------------- + * | | IMPL | VERS | | MID | | + * ---------------------------------------------------------- + * 64 31-28 27-24 23-22 21-17 16 0 + * + * IMPL: Implementation of this Spitfire. + * VERS: Version of this Spitfire. + * MID: Module ID of this processor. + */ + +#define SPITFIRE_MIDMASK 0x00000000003e0000 + +/* Spitfire Load Store Unit control register: + * + * --------------------------------------------------------------------- + * | RSV | PWR | PWW | VWR | VWW | RSV | PMASK | DME | IME | DCE | ICE | + * --------------------------------------------------------------------- + * 63-25 24 23 22 21 20 19-4 3 2 1 0 + * + * PWR: Physical Watchpoint Read enable: 0=off 1=on + * PWW: Physical Watchpoint Write enable: 0=off 1=on + * VWR: Virtual Watchpoint Read enable: 0=off 1=on + * VWW: Virtual Watchpoint Write enable: 0=off 1=on + * PMASK: Parity MASK ??? + * DME: Data MMU Enable: 0=off 1=on + * IME: Instruction MMU Enable: 0=off 1=on + * DCE: Data Cache Enable: 0=off 1=on + * ICE: Instruction Cache Enable: 0=off 1=on + */ + +#define SPITFIRE_LSU_PWR 0x01000000 +#define SPITFIRE_LSU_PWW 0x00800000 +#define SPITFIRE_LSU_VWR 0x00400000 +#define SPITFIRE_LSU_VWW 0x00200000 +#define SPITFIRE_LSU_PMASK 0x000ffff0 +#define SPITFIRE_LSU_DME 0x00000008 +#define SPITFIRE_LSU_IME 0x00000004 +#define SPITFIRE_LSU_DCE 0x00000002 +#define SPITFIRE_LSU_ICE 0x00000001 + +#endif /* !(_SPARC_ULTRA_H) */ diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h new file mode 100644 index 000000000..470b8fe59 --- /dev/null +++ b/include/asm-sparc/unaligned.h @@ -0,0 +1,19 @@ +#ifndef _ASM_SPARC_UNALIGNED_H_ +#define _ASM_SPARC_UNALIGNED_H_ + +/* Sparc can't handle unaligned accesses. */ + +#include <asm/string.h> + + +/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ + +#define get_unaligned(ptr) \ + ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) + +#define put_unaligned(val, ptr) \ + ({ __typeof__(*(ptr)) __tmp = (val); \ + memmove((ptr), &__tmp, sizeof(*(ptr))); \ + (void)0; }) + +#endif /* _ASM_SPARC_UNALIGNED_H */ diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index 3b0551461..468097d6f 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -1,3 +1,4 @@ +/* $Id: unistd.h,v 1.24 1996/08/29 09:49:06 davem Exp $ */ #ifndef _SPARC_UNISTD_H #define _SPARC_UNISTD_H @@ -8,19 +9,282 @@ * think of right now to force the arguments into fixed registers * before the trap into the system call with gcc 'asm' statements. * - * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * SunOS compatibility based upon preliminary work which is: + * + * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define __NR_setup 0 /* Used only by init, to get system going. */ +#define __NR_exit 1 /* Common */ +#define __NR_fork 2 /* Common */ +#define __NR_read 3 /* Common */ +#define __NR_write 4 /* Common */ +#define __NR_open 5 /* Common */ +#define __NR_close 6 /* Common */ +#define __NR_wait4 7 /* Common */ +#define __NR_creat 8 /* Common */ +#define __NR_link 9 /* Common */ +#define __NR_unlink 10 /* Common */ +#define __NR_execv 11 /* SunOS Specific */ +#define __NR_chdir 12 /* Common */ +/* #define __NR_ni_syscall 13 ENOSYS under SunOS */ +#define __NR_mknod 14 /* Common */ +#define __NR_chmod 15 /* Common */ +#define __NR_chown 16 /* Common */ +#define __NR_brk 17 /* Common */ +/* #define __NR_ni_syscall 18 ENOSYS under SunOS */ +#define __NR_lseek 19 /* Common */ +#define __NR_getpid 20 /* Common */ +/* #define __NR_ni_syscall 21 ENOSYS under SunOS */ +/* #define __NR_ni_syscall 22 ENOSYS under SunOS */ +#define __NR_setuid 23 /* Implemented via setreuid in SunOS */ +#define __NR_getuid 24 /* Common */ +/* #define __NR_ni_syscall 25 ENOSYS under SunOS */ +#define __NR_ptrace 26 /* Common */ +#define __NR_alarm 27 /* Implemented via setitimer in SunOS */ +/* #define __NR_ni_syscall 28 ENOSYS under SunOS */ +#define __NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */ +#define __NR_utime 30 /* Implemented via utimes() under SunOS */ +#define __NR_stty 31 /* Implemented via ioctl() under SunOS */ +#define __NR_gtty 32 /* Implemented via ioctl() under SunOS */ +#define __NR_access 33 /* Common */ +#define __NR_nice 34 /* Implemented via get/setpriority() in SunOS */ +#define __NR_ftime 35 /* Implemented via gettimeofday() in SunOS */ +#define __NR_sync 36 /* Common */ +#define __NR_kill 37 /* Common */ +#define __NR_stat 38 /* Common */ +/* #define __NR_ni_syscall 39 ENOSYS under SunOS */ +#define __NR_lstat 40 /* Common */ +#define __NR_dup 41 /* Common */ +#define __NR_pipe 42 /* Common */ +#define __NR_times 43 /* Implemented via getrusage() in SunOS */ +#define __NR_profil 44 /* Common */ +/* #define __NR_ni_syscall 45 ENOSYS under SunOS */ +#define __NR_setgid 46 /* Implemented via setregid() in SunOS */ +#define __NR_getgid 47 /* Common */ +#define __NR_signal 48 /* Implemented via sigvec() in SunOS */ +#define __NR_geteuid 49 /* SunOS calls getuid() */ +#define __NR_getegid 50 /* SunOS calls getgid() */ +#define __NR_acct 51 /* Common */ +/* #define __NR_ni_syscall 52 ENOSYS under SunOS */ +#define __NR_mctl 53 /* SunOS specific */ +#define __NR_ioctl 54 /* Common */ +#define __NR_reboot 55 /* Common */ +/* #define __NR_ni_syscall 56 ENOSYS under SunOS */ +#define __NR_symlink 57 /* Common */ +#define __NR_readlink 58 /* Common */ +#define __NR_execve 59 /* Common */ +#define __NR_umask 60 /* Common */ +#define __NR_chroot 61 /* Common */ +#define __NR_fstat 62 /* Common */ +/* #define __NR_ni_syscall 63 ENOSYS under SunOS */ +#define __NR_getpagesize 64 /* Common */ +#define __NR_msync 65 /* Common in newer 1.3.x revs... */ +/* #define __NR_ni_syscall 66 ENOSYS under SunOS */ +/* #define __NR_ni_syscall 67 ENOSYS under SunOS */ +/* #define __NR_ni_syscall 68 ENOSYS under SunOS */ +#define __NR_sbrk 69 /* SunOS Specific */ +#define __NR_sstk 70 /* SunOS Specific */ +#define __NR_mmap 71 /* Common */ +#define __NR_vadvise 72 /* SunOS Specific */ +#define __NR_munmap 73 /* Common */ +#define __NR_mprotect 74 /* Common */ +#define __NR_madvise 75 /* SunOS Specific */ +#define __NR_vhangup 76 /* Common */ +/* #define __NR_ni_syscall 77 ENOSYS under SunOS */ +#define __NR_mincore 78 /* SunOS Specific */ +#define __NR_getgroups 79 /* Common */ +#define __NR_setgroups 80 /* Common */ +#define __NR_getpgrp 81 /* Common */ +#define __NR_setpgrp 82 /* setpgid, same difference... */ +#define __NR_setitimer 83 /* Common */ +/* #define __NR_ni_syscall 84 ENOSYS under SunOS */ +#define __NR_swapon 85 /* Common */ +#define __NR_getitimer 86 /* Common */ +#define __NR_gethostname 87 /* SunOS Specific */ +#define __NR_sethostname 88 /* Common */ +#define __NR_getdtablesize 89 /* SunOS Specific */ +#define __NR_dup2 90 /* Common */ +#define __NR_getdopt 91 /* SunOS Specific */ +#define __NR_fcntl 92 /* Common */ +#define __NR_select 93 /* Common */ +#define __NR_setdopt 94 /* SunOS Specific */ +#define __NR_fsync 95 /* Common */ +#define __NR_setpriority 96 /* Common */ +#define __NR_socket 97 /* SunOS Specific */ +#define __NR_connect 98 /* SunOS Specific */ +#define __NR_accept 99 /* SunOS Specific */ +#define __NR_getpriority 100 /* Common */ +#define __NR_send 101 /* SunOS Specific */ +#define __NR_recv 102 /* SunOS Specific */ +/* #define __NR_ni_syscall 103 ENOSYS under SunOS */ +#define __NR_bind 104 /* SunOS Specific */ +#define __NR_setsockopt 105 /* SunOS Specific */ +#define __NR_listen 106 /* SunOS Specific */ +/* #define __NR_ni_syscall 107 ENOSYS under SunOS */ +#define __NR_sigvec 108 /* SunOS Specific */ +#define __NR_sigblock 109 /* SunOS Specific */ +#define __NR_sigsetmask 110 /* SunOS Specific */ +#define __NR_sigpause 111 /* SunOS Specific */ +#define __NR_sigstack 112 /* SunOS Specific */ +#define __NR_recvmsg 113 /* SunOS Specific */ +#define __NR_sendmsg 114 /* SunOS Specific */ +#define __NR_vtrace 115 /* SunOS Specific */ +#define __NR_gettimeofday 116 /* Common */ +#define __NR_getrusage 117 /* Common */ +#define __NR_getsockopt 118 /* SunOS Specific */ +/* #define __NR_ni_syscall 119 ENOSYS under SunOS */ +#define __NR_readv 120 /* Common */ +#define __NR_writev 121 /* Common */ +#define __NR_settimeofday 122 /* Common */ +#define __NR_fchown 123 /* Common */ +#define __NR_fchmod 124 /* Common */ +#define __NR_recvfrom 125 /* SunOS Specific */ +#define __NR_setreuid 126 /* Common */ +#define __NR_setregid 127 /* Common */ +#define __NR_rename 128 /* Common */ +#define __NR_truncate 129 /* Common */ +#define __NR_ftruncate 130 /* Common */ +#define __NR_flock 131 /* Common */ +/* #define __NR_ni_syscall 132 ENOSYS under SunOS */ +#define __NR_sendto 133 /* SunOS Specific */ +#define __NR_shutdown 134 /* SunOS Specific */ +#define __NR_socketpair 135 /* SunOS Specific */ +#define __NR_mkdir 136 /* Common */ +#define __NR_rmdir 137 /* Common */ +#define __NR_utimes 138 /* SunOS Specific */ +/* #define __NR_ni_syscall 139 ENOSYS under SunOS */ +#define __NR_adjtime 140 /* SunOS Specific */ +#define __NR_getpeername 141 /* SunOS Specific */ +#define __NR_gethostid 142 /* SunOS Specific */ +/* #define __NR_ni_syscall 143 ENOSYS under SunOS */ +#define __NR_getrlimit 144 /* Common */ +#define __NR_setrlimit 145 /* Common */ +#define __NR_killpg 146 /* SunOS Specific */ +/* #define __NR_ni_syscall 147 ENOSYS under SunOS */ +/* #define __NR_ni_syscall 148 ENOSYS under SunOS */ +/* #define __NR_ni_syscall 149 ENOSYS under SunOS */ +#define __NR_getsockname 150 /* SunOS Specific */ +#define __NR_getmsg 151 /* SunOS Specific */ +#define __NR_putmsg 152 /* SunOS Specific */ +#define __NR_poll 153 /* SunOS Specific */ +/* #define __NR_ni_syscall 154 ENOSYS under SunOS */ +#define __NR_nfssvc 155 /* SunOS Specific */ +#define __NR_getdirentries 156 /* SunOS Specific */ +#define __NR_statfs 157 /* Common */ +#define __NR_fstatfs 158 /* Common */ +#define __NR_umount 159 /* Common */ +#define __NR_async_daemon 160 /* SunOS Specific */ +#define __NR_getfh 161 /* SunOS Specific */ +#define __NR_getdomainname 162 /* SunOS Specific */ +#define __NR_setdomainname 163 /* Common */ +/* #define __NR_ni_syscall 164 ENOSYS under SunOS */ +#define __NR_quotactl 165 /* Common */ +#define __NR_exportfs 166 /* SunOS Specific */ +#define __NR_mount 167 /* Common */ +#define __NR_ustat 168 /* Common */ +#define __NR_semsys 169 /* SunOS Specific */ +#define __NR_msgsys 170 /* SunOS Specific */ +#define __NR_shmsys 171 /* SunOS Specific */ +#define __NR_auditsys 172 /* SunOS Specific */ +#define __NR_rfssys 173 /* SunOS Specific */ +#define __NR_getdents 174 /* Common */ +#define __NR_setsid 175 /* Common */ +#define __NR_fchdir 176 /* Common */ +#define __NR_fchroot 177 /* SunOS Specific */ +#define __NR_vpixsys 178 /* SunOS Specific */ +#define __NR_aioread 179 /* SunOS Specific */ +#define __NR_aiowrite 180 /* SunOS Specific */ +#define __NR_aiowait 181 /* SunOS Specific */ +#define __NR_aiocancel 182 /* SunOS Specific */ +#define __NR_sigpending 183 /* Common */ +/* #define __NR_ni_syscall 184 ENOSYS under SunOS */ +#define __NR_setpgid 185 /* Common */ +#define __NR_pathconf 186 /* SunOS Specific */ +#define __NR_fpathconf 187 /* SunOS Specific */ +#define __NR_sysconf 188 /* SunOS Specific */ +#define __NR_uname 189 /* Linux Specific */ +#define __NR_init_module 190 /* Linux Specific */ +#define __NR_personality 191 /* Linux Specific */ +#define __NR_prof 192 /* Linux Specific */ +#define __NR_break 193 /* Linux Specific */ +#define __NR_lock 194 /* Linux Specific */ +#define __NR_mpx 195 /* Linux Specific */ +#define __NR_ulimit 196 /* Linux Specific */ +#define __NR_getppid 197 /* Linux Specific */ +#define __NR_sigaction 198 /* Linux Specific */ +#define __NR_sgetmask 199 /* Linux Specific */ +#define __NR_ssetmask 200 /* Linux Specific */ +#define __NR_sigsuspend 201 /* Linux Specific */ +#define __NR_oldlstat 202 /* Linux Specific */ +#define __NR_uselib 203 /* Linux Specific */ +#define __NR_readdir 204 /* Linux Specific */ +#define __NR_ioperm 205 /* Linux Specific - i386 specific, unused */ +#define __NR_socketcall 206 /* Linux Specific */ +#define __NR_syslog 207 /* Linux Specific */ +#define __NR_olduname 208 /* Linux Specific */ +#define __NR_iopl 209 /* Linux Specific - i386 specific, unused */ +#define __NR_idle 210 /* Linux Specific */ +#define __NR_vm86 211 /* Linux Specific - i386 specific, unused */ +#define __NR_waitpid 212 /* Linux Specific */ +#define __NR_swapoff 213 /* Linux Specific */ +#define __NR_sysinfo 214 /* Linux Specific */ +#define __NR_ipc 215 /* Linux Specific */ +#define __NR_sigreturn 216 /* Linux Specific */ +#define __NR_clone 217 /* Linux Specific */ +#define __NR_modify_ldt 218 /* Linux Specific - i386 specific, unused */ +#define __NR_adjtimex 219 /* Linux Specific */ +#define __NR_sigprocmask 220 /* Linux Specific */ +#define __NR_create_module 221 /* Linux Specific */ +#define __NR_delete_module 222 /* Linux Specific */ +#define __NR_get_kernel_syms 223 /* Linux Specific */ +#define __NR_getpgid 224 /* Linux Specific */ +#define __NR_bdflush 225 /* Linux Specific */ +#define __NR_sysfs 226 /* Linux Specific */ +#define __NR_afs_syscall 227 /* Linux Specific */ +#define __NR_setfsuid 228 /* Linux Specific */ +#define __NR_setfsgid 229 /* Linux Specific */ +#define __NR__newselect 230 /* Linux Specific */ +#define __NR_time 231 /* Linux Specific */ +#define __NR_oldstat 232 /* Linux Specific */ +#define __NR_stime 233 /* Linux Specific */ +#define __NR_oldfstat 234 /* Linux Specific */ +#define __NR_phys 235 /* Linux Specific */ +#define __NR__llseek 236 /* Linux Specific */ +#define __NR_mlock 237 +#define __NR_munlock 238 +#define __NR_mlockall 239 +#define __NR_munlockall 240 +#define __NR_sched_setparam 241 +#define __NR_sched_getparam 242 +#define __NR_sched_setscheduler 243 +#define __NR_sched_getscheduler 244 +#define __NR_sched_yield 245 +#define __NR_sched_get_priority_max 246 +#define __NR_sched_get_priority_min 247 +#define __NR_sched_rr_get_interval 248 +#define __NR_nanosleep 249 +#define __NR_mremap 250 +#define __NR__sysctl 251 +#define __NR_getsid 252 +#define __NR_fdatasync 253 +#define __NR_nfsctl 254 + #define _syscall0(type,name) \ type name(void) \ { \ long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res) \ - : "0" (__NR_##name) \ - : "o0"); \ +__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res)\ + : "0" (__NR_##name) \ + : "g1", "o0"); \ if (__res >= 0) \ return (type) __res; \ errno = -__res; \ @@ -31,12 +295,16 @@ return -1; \ type name(type1 arg1) \ { \ long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "or %%g0, %1, %%o1\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res), "=r" ((long)(arg1)) \ - : "0" (__NR_##name),"1" ((long)(arg1)) \ - : "o0", "o1"); \ +__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \ + "or %%g0, %1, %%o0\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res), "=r" ((long)(arg1)) \ + : "0" (__NR_##name),"1" ((long)(arg1)) \ + : "g1", "o0"); \ if (__res >= 0) \ return (type) __res; \ errno = -__res; \ @@ -47,13 +315,17 @@ return -1; \ type name(type1 arg1,type2 arg2) \ { \ long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "or %%g0, %1, %%o1\n\t" \ - "or %%g0, %2, %%o2\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(args)) \ - : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \ - : "o0", "o1", "o2"); \ +__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \ + "or %%g0, %1, %%o0\n\t" \ + "or %%g0, %2, %%o1\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \ + : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \ + : "g1", "o0", "o1"); \ if (__res >= 0) \ return (type) __res; \ errno = -__res; \ @@ -64,19 +336,23 @@ return -1; \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "or %%g0, %1, %%o1\n\t" \ - "or %%g0, %2, %%o2\n\t" \ - "or %%g0, %3, %%o3\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \ - "=r" ((long)(arg3)) \ - : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \ - "3" ((long)(arg3)) \ - : "o0", "o1", "o2", "o3"); \ +__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \ + "or %%g0, %1, %%o0\n\t" \ + "or %%g0, %2, %%o1\n\t" \ + "or %%g0, %3, %%o2\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \ + "=r" ((long)(arg3)) \ + : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \ + "3" ((long)(arg3)) \ + : "g1", "o0", "o1", "o2"); \ if (__res>=0) \ return (type) __res; \ -errno=-__res; \ +errno = -__res; \ return -1; \ } @@ -84,20 +360,24 @@ return -1; \ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ { \ long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "or %%g0, %1, %%o1\n\t" \ - "or %%g0, %2, %%o2\n\t" \ - "or %%g0, %3, %%o3\n\t" \ - "or %%g0, %4, %%o4\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \ - "=r" ((long)(arg3)), "=r" ((long)(arg4)) \ - : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \ - "3" ((long)(arg3)),"4" ((long)(arg4)) \ - : "o0", "o1", "o2", "o3", "o4"); \ +__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \ + "or %%g0, %1, %%o0\n\t" \ + "or %%g0, %2, %%o1\n\t" \ + "or %%g0, %3, %%o2\n\t" \ + "or %%g0, %4, %%o3\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0,%%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \ + "=r" ((long)(arg3)), "=r" ((long)(arg4)) \ + : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \ + "3" ((long)(arg3)),"4" ((long)(arg4)) \ + : "g1", "o0", "o1", "o2", "o3"); \ if (__res>=0) \ return (type) __res; \ -errno=-__res; \ +errno = -__res; \ return -1; \ } @@ -105,25 +385,29 @@ return -1; \ type5,arg5) \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ { \ -long __res; \ -__asm__ volatile ("or %%g0, %0, %%o0\n\t" \ - "or %%g0, %1, %%o1\n\t" \ - "or %%g0, %2, %%o2\n\t" \ - "or %%g0, %3, %%o3\n\t" \ - "or %%g0, %4, %%o4\n\t" \ - "or %%g0, %5, %%o5\n\t" \ - "t 0xa\n\t" \ - : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \ - "=r" ((long)(arg3)), "=r" ((long)(arg4)), "=r" ((long)(arg5)) \ - : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \ - "3" ((long)(arg3)),"4" ((long)(arg4)),"5" ((long)(arg5)) \ - : "o0", "o1", "o2", "o3", "o4", "o5"); \ + long __res; \ +\ +__asm__ __volatile__ ("or %%g0, %1, %%o0\n\t" \ + "or %%g0, %2, %%o1\n\t" \ + "or %%g0, %3, %%o2\n\t" \ + "or %%g0, %4, %%o3\n\t" \ + "or %%g0, %5, %%o4\n\t" \ + "or %%g0, %6, %%g1\n\t" \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "or %%g0, %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)), \ + "r" ((long)(arg3)),"r" ((long)(arg4)),"r" ((long)(arg5)), \ + "i" (__NR_##name) \ + : "g1", "o0", "o1", "o2", "o3", "o4"); \ if (__res>=0) \ return (type) __res; \ -errno=-__res; \ +errno = -__res; \ return -1; \ } - #ifdef __KERNEL_SYSCALLS__ /* @@ -139,25 +423,70 @@ return -1; \ * some others too. */ #define __NR__exit __NR_exit -static inline _syscall0(int,idle) -static inline _syscall0(int,fork) -static inline _syscall0(int,pause) -static inline _syscall0(int,setup) -static inline _syscall0(int,sync) -static inline _syscall0(pid_t,setsid) -static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) -static inline _syscall1(int,dup,int,fd) -static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -static inline _syscall3(int,open,const char *,file,int,flag,int,mode) -static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) -static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) +static __inline__ _syscall0(int,idle) +static __inline__ _syscall0(int,fork) +static __inline__ _syscall2(int,clone,unsigned long,flags,char *,ksp) +static __inline__ _syscall0(int,pause) +static __inline__ _syscall0(int,setup) +static __inline__ _syscall0(int,sync) +static __inline__ _syscall0(pid_t,setsid) +static __inline__ _syscall3(int,write,int,fd,__const__ char *,buf,off_t,count) +static __inline__ _syscall1(int,dup,int,fd) +static __inline__ _syscall3(int,execve,__const__ char *,file,char **,argv,char **,envp) +static __inline__ _syscall3(int,open,__const__ char *,file,int,flag,int,mode) +static __inline__ _syscall1(int,close,int,fd) +static __inline__ _syscall1(int,_exit,int,exitcode) +static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) -static inline pid_t wait(int * wait_stat) +static __inline__ pid_t wait(int * wait_stat) { return waitpid(-1,wait_stat,0); } -#endif +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be free'd until both the parent and the child have exited. + */ +static __inline__ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile("mov %4, %%g2\n\t" /* Set aside fn ptr... */ + "mov %5, %%g3\n\t" /* and arg. */ + "mov %1, %%g1\n\t" + "mov %2, %%o0\n\t" /* Clone flags. */ + "mov 0, %%o1\n\t" /* usp arg == 0 */ + "t 0x10\n\t" /* Linux/Sparc clone(). */ + "cmp %%o1, 0\n\t" + "be 1f\n\t" /* The parent, just return. */ + " nop\n\t" /* Delay slot. */ + "jmpl %%g2, %%o7\n\t" /* Call the function. */ + " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ + "mov %3, %%g1\n\t" + "t 0x10\n\t" /* Linux/Sparc exit(). */ + /* Notreached by child. */ + "1: mov %%o0, %0\n\t" : + "=r" (retval) : + "i" (__NR_clone), "r" (flags | CLONE_VM), + "i" (__NR_exit), "r" (fn), "r" (arg) : + "g1", "g2", "g3", "o0", "o1", "memory"); + return retval; +} + +#endif /* __KERNEL_SYSCALLS__ */ + +/* sysconf options, for SunOS compatibility */ +#define _SC_ARG_MAX 1 +#define _SC_CHILD_MAX 2 +#define _SC_CLK_TCK 3 +#define _SC_NGROUPS_MAX 4 +#define _SC_OPEN_MAX 5 +#define _SC_JOB_CONTROL 6 +#define _SC_SAVED_IDS 7 +#define _SC_VERSION 8 #endif /* _SPARC_UNISTD_H */ diff --git a/include/asm-sparc/user.h b/include/asm-sparc/user.h new file mode 100644 index 000000000..7306b0d10 --- /dev/null +++ b/include/asm-sparc/user.h @@ -0,0 +1,60 @@ +/* $Id: user.h,v 1.4 1996/07/24 23:17:14 miguel Exp $ + * asm-sparc/user.h: Core file definitions for the Sparc. + * + * Keep in sync with reg.h. Actually, we could get rid of this + * one, since we won't a.out core dump that much anyways - miguel. + * Copyright (C) 1995 (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_USER_H +#define _SPARC_USER_H + +#include <asm/a.out.h> +struct sunos_regs { + unsigned long psr, pc, npc, y; + unsigned long regs[15]; +}; + +struct sunos_fpqueue { + unsigned long *addr; + unsigned long inst; +}; + +struct sunos_fp { + union { + unsigned long regs[32]; + double reg_dbls[16]; + } fregs; + unsigned long fsr; + unsigned long flags; + unsigned long extra; + unsigned long fpq_count; + struct sunos_fpqueue fpq[16]; +}; + +struct sunos_fpu { + struct sunos_fp fpstatus; +}; + +/* The SunOS core file header layout. */ +struct user { + unsigned long magic; + unsigned long len; + struct sunos_regs regs; + struct exec uexec; + int signal; + size_t u_tsize; /* all of these in bytes! */ + size_t u_dsize; + size_t u_ssize; + char u_comm[17]; + struct sunos_fpu fpu; + unsigned long sigcode; /* Special sigcontext subcode, if any */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +#define SUNOS_CORE_MAGIC 0x080456 + +#endif /* !(_SPARC_USER_H) */ diff --git a/include/asm-sparc/vac-ops.h b/include/asm-sparc/vac-ops.h index 18755e048..d963a7fa3 100644 --- a/include/asm-sparc/vac-ops.h +++ b/include/asm-sparc/vac-ops.h @@ -1,89 +1,125 @@ +/* $Id: vac-ops.h,v 1.12 1996/07/08 15:12:30 ecd Exp $ */ #ifndef _SPARC_VAC_OPS_H #define _SPARC_VAC_OPS_H /* vac-ops.h: Inline assembly routines to do operations on the Sparc - VAC (virtual address cache). - - Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu) -*/ - -extern unsigned long *trapbase; -extern char end, etext, msgbuf; - -extern void flush_vac_context(void); -extern void flush_vac_segment(unsigned int foo_segment); -extern void flush_vac_page(unsigned int foo_addr); - -extern int vac_do_hw_vac_flushes, vac_size, vac_linesize; -extern int vac_entries_per_context, vac_entries_per_segment; -extern int vac_entries_per_page; - -/* enable_vac() enables the virtual address cache. It returns 0 on - success, 1 on failure. -*/ - -extern __inline__ int enable_vac(void) -{ - int success=0; - - __asm__ __volatile__("lduba [%1] 2, %0\n\t" - "or %0, 0x10, %0\n\t" - "stba %0, [%1] 2\n\t" - "or %%g0, %%g0, %0" : - "=r" (success) : - "r" ((unsigned int) 0x40000000), - "0" (success)); - return success; -} - -/* disable_vac() disables the virtual address cache. It returns 0 on - success, 1 on failure. -*/ - -extern __inline__ int disable_vac(void) + * VAC (virtual address cache) for the sun4c. + * + * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu) + */ + +#include <asm/sysen.h> +#include <asm/contregs.h> +#include <asm/asi.h> + +/* The SUN4C models have a virtually addressed write-through + * cache. + * + * The cache tags are directly accessible through an ASI and + * each have the form: + * + * ------------------------------------------------------------ + * | MBZ | CONTEXT | WRITE | PRIV | VALID | MBZ | TagID | MBZ | + * ------------------------------------------------------------ + * 31 25 24 22 21 20 19 18 16 15 2 1 0 + * + * MBZ: These bits are either unused and/or reserved and should + * be written as zeroes. + * + * CONTEXT: Records the context to which this cache line belongs. + * + * WRITE: A copy of the writable bit from the mmu pte access bits. + * + * PRIV: A copy of the privileged bit from the pte access bits. + * + * VALID: If set, this line is valid, else invalid. + * + * TagID: Fourteen bits of tag ID. + * + * Every virtual address is seen by the cache like this: + * + * ---------------------------------------- + * | RESV | TagID | LINE | BYTE-in-LINE | + * ---------------------------------------- + * 31 30 29 16 15 4 3 0 + * + * RESV: Unused/reserved. + * + * TagID: Used to match the Tag-ID in that vac tags. + * + * LINE: Which line within the cache + * + * BYTE-in-LINE: Which byte within the cache line. + */ + +/* Sun4c VAC Tags */ +#define S4CVACTAG_CID 0x01c00000 +#define S4CVACTAG_W 0x00200000 +#define S4CVACTAG_P 0x00100000 +#define S4CVACTAG_V 0x00080000 +#define S4CVACTAG_TID 0x0000fffc + +/* Sun4c VAC Virtual Address */ +#define S4CVACVA_TID 0x3fff0000 +#define S4CVACVA_LINE 0x0000fff0 +#define S4CVACVA_BIL 0x0000000f + +/* The indexing of cache lines creates a problem. Because the line + * field of a virtual address extends past the page offset within + * the virtual address it is possible to have what are called + * 'bad aliases' which will create inconsistencies. So we must make + * sure that within a context that if a physical page is mapped + * more than once, that 'extra' line bits are the same. If this is + * not the case, and thus is a 'bad alias' we must turn off the + * cacheable bit in the pte's of all such pages. + */ +#define S4CVAC_BADBITS 0x0000f000 + +/* The following is true if vaddr1 and vaddr2 would cause + * a 'bad alias'. + */ +#define S4CVAC_BADALIAS(vaddr1, vaddr2) \ + ((((unsigned long) (vaddr1)) ^ ((unsigned long) (vaddr2))) & \ + (S4CVAC_BADBITS)) + +/* The following structure describes the characteristics of a sun4c + * VAC as probed from the prom during boot time. + */ +struct sun4c_vac_props { + unsigned int num_bytes; /* Size of the cache */ + unsigned int num_lines; /* Number of cache lines */ + unsigned int do_hwflushes; /* Hardware flushing available? */ + unsigned int linesize; /* Size of each line in bytes */ + unsigned int log2lsize; /* log2(linesize) */ + unsigned int on; /* VAC is enabled */ +}; + +extern struct sun4c_vac_props sun4c_vacinfo; + +extern void sun4c_flush_all(void); + +/* sun4c_enable_vac() enables the sun4c virtual address cache. */ +extern __inline__ void sun4c_enable_vac(void) { - int success=0; - - __asm__ __volatile__("lduba [%1] 0x2, %0\n\t" - "xor %0, 0x10, %0\n\t" - "stba %0, [%1] 0x2\n\t" - "or %%g0, %%g0, %0" : - "=r" (success) : - "r" (0x40000000), - "0" (success)); - return success; + __asm__ __volatile__("lduba [%0] %1, %%g1\n\t" + "or %%g1, %2, %%g1\n\t" + "stba %%g1, [%0] %1\n\t" : : + "r" ((unsigned int) AC_SENABLE), + "i" (ASI_CONTROL), "i" (SENABLE_CACHE) : + "g1"); + sun4c_vacinfo.on = 1; } -/* Various one-shot VAC entry flushes on the Sparc */ - -extern __inline__ void hw_flush_vac_context_entry(char* addr) +/* sun4c_disable_vac() disables the virtual address cache. */ +extern __inline__ void sun4c_disable_vac(void) { - __asm__ __volatile__("sta %%g0, [%0] 0x7" : : "r" (addr)); + __asm__ __volatile__("lduba [%0] %1, %%g1\n\t" + "andn %%g1, %2, %%g1\n\t" + "stba %%g1, [%0] %1\n\t" : : + "r" ((unsigned int) AC_SENABLE), + "i" (ASI_CONTROL), "i" (SENABLE_CACHE) : + "g1"); + sun4c_vacinfo.on = 0; } -extern __inline__ void sw_flush_vac_context_entry(char* addr) -{ - __asm__ __volatile__("sta %%g0, [%0] 0xe" : : "r" (addr)); -} - -extern __inline__ void hw_flush_vac_segment_entry(char* addr) -{ - __asm__ __volatile__("sta %%g0, [%0] 0x5" : : "r" (addr)); -} - -extern __inline__ void sw_flush_vac_segment_entry(char* addr) -{ - __asm__ __volatile__("sta %%g0, [%0] 0xc" : : "r" (addr)); -} - -extern __inline__ void hw_flush_vac_page_entry(unsigned long* addr) -{ - __asm__ __volatile__("sta %%g0, [%0] 0x6" : : "r" (addr)); -} - -extern __inline__ void sw_flush_vac_page_entry(unsigned long* addr) -{ - __asm__ __volatile__("sta %%g0, [%0] 0xd" : : "r" (addr)); -} - #endif /* !(_SPARC_VAC_OPS_H) */ diff --git a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h index 7df443103..30e927b1b 100644 --- a/include/asm-sparc/vaddrs.h +++ b/include/asm-sparc/vaddrs.h @@ -1,6 +1,9 @@ +/* $Id: vaddrs.h,v 1.21 1996/10/07 03:03:02 davem Exp $ */ #ifndef _SPARC_VADDRS_H #define _SPARC_VADDRS_H +#include <asm/head.h> + /* asm-sparc/vaddrs.h: Here will be define the virtual addresses at * which important I/O addresses will be mapped. * For instance the timer register virtual address @@ -9,8 +12,54 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#define TIMER_VADDR 0x3000 /* Next page after where the interrupt enable - * register gets mapped at boot. - */ +/* I can see only one reason why we should have statically defined + * mappings for devices and is the speedup improvements of not loading + * a pointer and then the value in the assembly code + */ +#define IOBASE_VADDR 0xfe000000 /* Base for mapping pages */ +#define IOBASE_LEN 0x00300000 /* Length of the IO area */ +#define IOBASE_END 0xfe300000 +#define DVMA_VADDR 0xfff00000 /* Base area of the DVMA on suns */ +#define DVMA_LEN 0x00040000 /* Size of the DVMA address space */ +#define DVMA_END 0xfff40000 + +/* IOMMU Mapping area, must be on a 16MB boundary! Note this + * doesn't count the DVMA areas, the prom lives between the + * iommu mapping area (for scsi transfer buffers) and the + * dvma upper range (for lance packet ring buffers). + */ +#define IOMMU_VADDR 0xff000000 +#define IOMMU_LEN 0x00c00000 +#define IOMMU_END 0xffc00000 /* KADB debugger vm starts here */ + +/* On the sun4/4c we don't need an IOMMU area, but we need a place + * to reliably map locked down kernel data. This includes the + * task_struct and kernel stack pages of each process plus the + * scsi buffers during dvma IO transfers, also the floppy buffers + * during pseudo dma which runs with traps off (no faults allowed). + * Some quick calculations yield: + * NR_TASKS <512> * (3 * PAGE_SIZE) == 0x600000 + * Subtract this from 0xc00000 and you get 0x927C0 of vm left + * over to map SCSI dvma + floppy pseudo-dma buffers. So be + * careful if you change NR_TASKS or else there won't be enough + * room for it all. + */ +#define SUN4C_LOCK_VADDR 0xff000000 +#define SUN4C_LOCK_LEN 0x00c00000 +#define SUN4C_LOCK_END 0xffc00000 + +/* On sun4m machines we need per-cpu virtual areas */ +#define PERCPU_VADDR 0xffc00000 /* Base for per-cpu virtual mappings */ +#define PERCPU_ENTSIZE 0x00100000 +#define PERCPU_LEN ((PERCPU_ENTSIZE*NCPUS)) + +/* per-cpu offsets */ +#define PERCPU_TBR_OFFSET 0x00000 /* %tbr, mainly used for identification. */ +#define PERCPU_KSTACK_OFFSET 0x01000 /* Beginning of kernel stack for this cpu */ +#define PERCPU_MBOX_OFFSET 0x03000 /* Prom SMP Mailbox */ +#define PERCPU_CPUID_OFFSET 0x04000 /* Per-cpu ID number. */ +#define PERCPU_ISALIVE_OFFSET 0x04004 /* Has CPU been initted yet? */ +#define PERCPU_ISIDLING_OFFSET 0x04008 /* Is CPU in idle loop spinning? */ #endif /* !(_SPARC_VADDRS_H) */ + diff --git a/include/asm-sparc/version.h b/include/asm-sparc/version.h deleted file mode 100644 index 0c238e9cf..000000000 --- a/include/asm-sparc/version.h +++ /dev/null @@ -1 +0,0 @@ -#define WHO_COMPILED_ME "someone@somewhere.domain" diff --git a/include/asm-sparc/viking.h b/include/asm-sparc/viking.h new file mode 100644 index 000000000..dc4adc393 --- /dev/null +++ b/include/asm-sparc/viking.h @@ -0,0 +1,198 @@ +/* $Id: viking.h,v 1.16 1996/08/29 09:49:10 davem Exp $ + * viking.h: Defines specific to the GNU/Viking MBUS module. + * This is SRMMU stuff. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _SPARC_VIKING_H +#define _SPARC_VIKING_H + +#include <asm/asi.h> +#include <asm/mxcc.h> + +/* Bits in the SRMMU control register for GNU/Viking modules. + * + * ----------------------------------------------------------- + * |impl-vers| RSV |TC|AC|SP|BM|PC|MBM|SB|IC|DC|PSO|RSV|NF|ME| + * ----------------------------------------------------------- + * 31 24 23-17 16 15 14 13 12 11 10 9 8 7 6-2 1 0 + * + * TC: Tablewalk Cacheable -- 0 = Twalks are not cacheable in E-cache + * 1 = Twalks are cacheable in E-cache + * + * GNU/Viking will only cache tablewalks in the E-cache (mxcc) if present + * and never caches them internally (or so states the docs). Therefore + * for machines lacking an E-cache (ie. in MBUS mode) this bit must + * remain cleared. + * + * AC: Alternate Cacheable -- 0 = Passthru physical accesses not cacheable + * 1 = Passthru physical accesses cacheable + * + * This indicates whether accesses are cacheable when no cachable bit + * is present in the pte when the processor is in boot-mode or the + * access does not need pte's for translation (ie. pass-thru ASI's). + * "Cachable" is only referring to E-cache (if present) and not the + * on chip split I/D caches of the GNU/Viking. + * + * SP: SnooP Enable -- 0 = bus snooping off, 1 = bus snooping on + * + * This enables snooping on the GNU/Viking bus. This must be on + * for the hardware cache consistency mechanisms of the GNU/Viking + * to work at all. On non-mxcc GNU/Viking modules the split I/D + * caches will snoop regardless of whether they are enabled, this + * takes care of the case where the I or D or both caches are turned + * off yet still contain valid data. Note also that this bit does + * not affect GNU/Viking store-buffer snoops, those happen if the + * store-buffer is enabled no matter what. + * + * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode + * + * This indicates whether the GNU/Viking is in boot-mode or not, + * if it is then all instruction fetch physical addresses are + * computed as 0xff0000000 + low 28 bits of requested address. + * GNU/Viking boot-mode does not affect data accesses. Also, + * in boot mode instruction accesses bypass the split on chip I/D + * caches, they may be cached by the GNU/MXCC if present and enabled. + * + * MBM: MBus Mode -- 0 = not in MBus mode, 1 = in MBus mode + * + * This indicated the GNU/Viking configuration present. If in + * MBUS mode, the GNU/Viking lacks a GNU/MXCC E-cache. If it is + * not then the GNU/Viking is on a module VBUS connected directly + * to a GNU/MXCC cache controller. The GNU/MXCC can be thus connected + * to either an GNU/MBUS (sun4m) or the packet-switched GNU/XBus (sun4d). + * + * SB: StoreBuffer enable -- 0 = store buffer off, 1 = store buffer on + * + * The GNU/Viking store buffer allows the chip to continue execution + * after a store even if the data cannot be placed in one of the + * caches during that cycle. If disabled, all stores operations + * occur synchronously. + * + * IC: Instruction Cache -- 0 = off, 1 = on + * DC: Data Cache -- 0 = off, 1 = 0n + * + * These bits enable the on-cpu GNU/Viking split I/D caches. Note, + * as mentioned above, these caches will snoop the bus in GNU/MBUS + * configurations even when disabled to avoid data corruption. + * + * NF: No Fault -- 0 = faults generate traps, 1 = faults don't trap + * ME: MMU enable -- 0 = mmu not translating, 1 = mmu translating + * + */ + +#define VIKING_MMUENABLE 0x00000001 +#define VIKING_NOFAULT 0x00000002 +#define VIKING_PSO 0x00000080 +#define VIKING_DCENABLE 0x00000100 /* Enable data cache */ +#define VIKING_ICENABLE 0x00000200 /* Enable instruction cache */ +#define VIKING_SBENABLE 0x00000400 /* Enable store buffer */ +#define VIKING_MMODE 0x00000800 /* MBUS mode */ +#define VIKING_PCENABLE 0x00001000 /* Enable parity checking */ +#define VIKING_BMODE 0x00002000 +#define VIKING_SPENABLE 0x00004000 /* Enable bus cache snooping */ +#define VIKING_ACENABLE 0x00008000 /* Enable alternate caching */ +#define VIKING_TCENABLE 0x00010000 /* Enable table-walks to be cached */ +#define VIKING_DPENABLE 0x00040000 /* Enable the data prefetcher */ + +/* + * GNU/Viking Breakpoint Action Register fields. + */ +#define VIKING_ACTION_MIX 0x00001000 /* Enable multiple instructions */ + +/* + * GNU/Viking Cache Tags. + */ +#define VIKING_PTAG_VALID 0x01000000 /* Cache block is valid */ +#define VIKING_PTAG_DIRTY 0x00010000 /* Block has been modified */ +#define VIKING_PTAG_SHARED 0x00000100 /* Shared with some other cache */ + +extern __inline__ void viking_flush_icache(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_IC_FLCLEAR)); +} + +extern __inline__ void viking_flush_dcache(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : + "i" (ASI_M_DC_FLCLEAR)); +} + +extern __inline__ void viking_unlock_icache(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (0x80000000), "i" (ASI_M_IC_FLCLEAR)); +} + +extern __inline__ void viking_unlock_dcache(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (0x80000000), "i" (ASI_M_DC_FLCLEAR)); +} + +extern __inline__ void viking_set_bpreg(unsigned long regval) +{ + __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : : + "r" (regval), + "i" (ASI_M_ACTION)); +} + +extern __inline__ unsigned long viking_get_bpreg(void) +{ + unsigned long regval; + + __asm__ __volatile__("lda [%%g0] %1, %0\n\t" : + "=r" (regval) : + "i" (ASI_M_ACTION)); + return regval; +} + +extern __inline__ void viking_get_dcache_ptag(int set, int block, + unsigned long *data) +{ + unsigned long ptag = ((set & 0x7f) << 5) | ((block & 0x3) << 26) | + 0x80000000; + unsigned long info, page; + + __asm__ __volatile__ ("ldda [%2] %3, %%g2\n\t" + "or %%g0, %%g2, %0\n\t" + "or %%g0, %%g3, %1\n\t" : + "=r" (info), "=r" (page) : + "r" (ptag), "i" (ASI_M_DATAC_TAG) : + "g2", "g3"); + data[0] = info; + data[1] = page; +} + +extern __inline__ void viking_mxcc_turn_off_parity(unsigned long *mregp, + unsigned long *mxcc_cregp) +{ + unsigned long mreg = *mregp; + unsigned long mxcc_creg = *mxcc_cregp; + + mreg &= ~(VIKING_PCENABLE); + mxcc_creg &= ~(MXCC_CTL_PARE); + + __asm__ __volatile__ ("set 1f, %%g2\n\t" + "andcc %%g2, 4, %%g0\n\t" + "bne 2f\n\t" + " nop\n" + "1:\n\t" + "sta %0, [%%g0] %3\n\t" + "sta %1, [%2] %4\n\t" + "b 1f\n\t" + " nop\n\t" + "nop\n" + "2:\n\t" + "sta %0, [%%g0] %3\n\t" + "sta %1, [%2] %4\n" + "1:\n\t" : : + "r" (mreg), "r" (mxcc_creg), + "r" (MXCC_CREG), "i" (ASI_M_MMUREGS), + "i" (ASI_M_MXCC) : "g2"); + *mregp = mreg; + *mxcc_cregp = mxcc_creg; +} + +#endif /* !(_SPARC_VIKING_H) */ diff --git a/include/asm-sparc/vuid_event.h b/include/asm-sparc/vuid_event.h new file mode 100644 index 000000000..7781e9f2f --- /dev/null +++ b/include/asm-sparc/vuid_event.h @@ -0,0 +1,41 @@ +/* SunOS Virtual User Input Device (VUID) compatibility */ + + +typedef struct firm_event { + unsigned short id; /* tag for this event */ + unsigned char pair_type; /* unused by X11 */ + unsigned char pair; /* unused by X11 */ + int value; /* VKEY_UP, VKEY_DOWN or delta */ + struct timeval time; +} Firm_event; + +enum { + FE_PAIR_NONE, + FE_PAIR_SET, + FE_PAIR_DELTA, + FE_PAIR_ABSOLUTE +}; + +/* VUID stream formats */ +#define VUID_NATIVE 0 /* Native byte stream format */ +#define VUID_FIRM_EVENT 1 /* send firm_event structures */ + +/* ioctls */ + /* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */ +#define VUIDSFORMAT _IOW('v', 1, int) + /* Retrieve input device byte stream format */ +#define VUIDGFORMAT _IOR('v', 2, int) + +/* Possible tag values */ +/* mouse buttons: */ +#define MS_LEFT 0x7f20 +#define MS_MIDDLE 0x7f21 +#define MS_RIGHT 0x7f22 +/* motion: */ +#define LOC_X_DELTA 0x7f80 +#define LOC_Y_DELTA 0x7f81 +#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */ +#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */ + +#define VKEY_UP 0 +#define VKEY_DOWN 1 diff --git a/include/asm-sparc/wim.h b/include/asm-sparc/wim.h deleted file mode 100644 index 74b0a65a9..000000000 --- a/include/asm-sparc/wim.h +++ /dev/null @@ -1,56 +0,0 @@ -/* wim.h: Defines the layout of the "Window Invalid Register" on - Version 8 of the Sparc Architecture. - - Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) -*/ - -#ifndef __LINUX_SPARC_WIM_H -#define __LINUX_SPARC_WIM_H - -#ifdef __LINUX_SPARC_V8 /* register doesn't exist on the V9 */ - -/* The Window Invalid Register %wim, holds a set of which register - windows are 'valid' at this point in time. - - ------------------------------------------------------------ - |W31|W30|W29|W28|W27|W26|W25|W24|W23|....|W5|W4|W3|W2|W1|W0| - ------------------------------------------------------------ - - Each register window on the chip gets one bit. If the bit is - set then the window is currently 'invalid' and hardware will - trap if that window is entered via a 'save', 'restore', or - 'rett' instruction. Privileged software is responsible for - updating this on trap fills/spills etc. Therefore if a 'save' - instruction is executed and it causes the Current Window - Pointer to equal a register window which has its bit set in - %wim we get a 'overflow' trap, a restore into such a register - invokes a window 'spill' trap. -*/ - -#define __LINUX_SPARC_HAS_WIM - -/* Macro to fine the %wim bit mask for the current window pointer */ -#define CWP_TO_WIM_MASK(cwp) (1<<(cwp)) - -/* Assembly version of above macro, 'cwp' and 'wimask' must be registers */ -#define ASM_CWP_TO_WIM_MASK(cwp,wimask) \ - or %g0, 0x1, wimask \ - sll wimask, cwp, wimask - -/* Assembly macro to find if the given window is set to invalid in the %wim. - Again 'window', 'result', and 'scratch' must be in registers. This leaves - a non-zero value in result if the window is indeed invalid. This routine - works because we keep exactly one window invalid at all times to maximize - register utilization, which means both kernel and user windows can be in - the register file at the same time in certain trap situations. -*/ -#define ASM_REG_WIN_INVAL(window,result,scratch) \ - rd %wim, result \ - or %g0, 0x1, scratch \ - sll scratch, window, scratch \ - and scratch, result, result - -#endif /* !(__LINUX_SPARC_V8) */ - -#endif /* !(__LINUX_SPARC_WIM_H) */ - diff --git a/include/asm-sparc/winmacro.h b/include/asm-sparc/winmacro.h new file mode 100644 index 000000000..e0cc5d3c9 --- /dev/null +++ b/include/asm-sparc/winmacro.h @@ -0,0 +1,129 @@ +/* $Id: winmacro.h,v 1.17 1996/09/19 20:27:44 davem Exp $ + * winmacro.h: Window loading-unloading macros. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_WINMACRO_H +#define _SPARC_WINMACRO_H + +#include <asm/ptrace.h> +#include <asm/psr.h> + +/* These are just handy. */ +#define _SV save %sp, -REGWIN_SZ, %sp +#define _RS restore + +#define FLUSH_ALL_KERNEL_WINDOWS \ + _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ + _RS; _RS; _RS; _RS; _RS; _RS; _RS; + +/* Store the register window onto the 8-byte aligned area starting + * at %reg. It might be %sp, it might not, we don't care. + */ +#define STORE_WINDOW(reg) \ + std %l0, [%reg + RW_L0]; \ + std %l2, [%reg + RW_L2]; \ + std %l4, [%reg + RW_L4]; \ + std %l6, [%reg + RW_L6]; \ + std %i0, [%reg + RW_I0]; \ + std %i2, [%reg + RW_I2]; \ + std %i4, [%reg + RW_I4]; \ + std %i6, [%reg + RW_I6]; + +/* Load a register window from the area beginning at %reg. */ +#define LOAD_WINDOW(reg) \ + ldd [%reg + RW_L0], %l0; \ + ldd [%reg + RW_L2], %l2; \ + ldd [%reg + RW_L4], %l4; \ + ldd [%reg + RW_L6], %l6; \ + ldd [%reg + RW_I0], %i0; \ + ldd [%reg + RW_I2], %i2; \ + ldd [%reg + RW_I4], %i4; \ + ldd [%reg + RW_I6], %i6; + +/* Loading and storing struct pt_reg trap frames. */ +#define LOAD_PT_INS(base_reg) \ + ldd [%base_reg + REGWIN_SZ + PT_I0], %i0; \ + ldd [%base_reg + REGWIN_SZ + PT_I2], %i2; \ + ldd [%base_reg + REGWIN_SZ + PT_I4], %i4; \ + ldd [%base_reg + REGWIN_SZ + PT_I6], %i6; + +#define LOAD_PT_GLOBALS(base_reg) \ + ld [%base_reg + REGWIN_SZ + PT_G1], %g1; \ + ldd [%base_reg + REGWIN_SZ + PT_G2], %g2; \ + ldd [%base_reg + REGWIN_SZ + PT_G4], %g4; \ + ldd [%base_reg + REGWIN_SZ + PT_G6], %g6; + +#define LOAD_PT_YREG(base_reg, scratch) \ + ld [%base_reg + REGWIN_SZ + PT_Y], %scratch; \ + wr %scratch, 0x0, %y; + +#define LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \ + ld [%base_reg + REGWIN_SZ + PT_PSR], %pt_psr; \ + ld [%base_reg + REGWIN_SZ + PT_PC], %pt_pc; \ + ld [%base_reg + REGWIN_SZ + PT_NPC], %pt_npc; + +#define LOAD_PT_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \ + LOAD_PT_YREG(base_reg, scratch) \ + LOAD_PT_INS(base_reg) \ + LOAD_PT_GLOBALS(base_reg) \ + LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) + +#define STORE_PT_INS(base_reg) \ + std %i0, [%base_reg + REGWIN_SZ + PT_I0]; \ + std %i2, [%base_reg + REGWIN_SZ + PT_I2]; \ + std %i4, [%base_reg + REGWIN_SZ + PT_I4]; \ + std %i6, [%base_reg + REGWIN_SZ + PT_I6]; + +#define STORE_PT_GLOBALS(base_reg) \ + st %g1, [%base_reg + REGWIN_SZ + PT_G1]; \ + std %g2, [%base_reg + REGWIN_SZ + PT_G2]; \ + std %g4, [%base_reg + REGWIN_SZ + PT_G4]; \ + std %g6, [%base_reg + REGWIN_SZ + PT_G6]; + +#define STORE_PT_YREG(base_reg, scratch) \ + rd %y, %scratch; \ + st %scratch, [%base_reg + REGWIN_SZ + PT_Y]; + +#define STORE_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \ + st %pt_psr, [%base_reg + REGWIN_SZ + PT_PSR]; \ + st %pt_pc, [%base_reg + REGWIN_SZ + PT_PC]; \ + st %pt_npc, [%base_reg + REGWIN_SZ + PT_NPC]; + +#define STORE_PT_ALL(base_reg, reg_psr, reg_pc, reg_npc, g_scratch) \ + STORE_PT_PRIV(base_reg, reg_psr, reg_pc, reg_npc) \ + STORE_PT_GLOBALS(base_reg) \ + STORE_PT_YREG(base_reg, g_scratch) \ + STORE_PT_INS(base_reg) + +#define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \ + ld [%cur_reg + THREAD_W_SAVED], %scratch; \ + sll %scratch, 2, %scratch; \ + add %scratch, %cur_reg, %scratch; \ + st %sp, [%scratch + THREAD_STACK_PTRS]; \ + sub %scratch, %cur_reg, %scratch; \ + sll %scratch, 4, %scratch; \ + add %scratch, %cur_reg, %scratch; \ + STORE_WINDOW(scratch + THREAD_REG_WINDOW); \ + sub %scratch, %cur_reg, %scratch; \ + srl %scratch, 6, %scratch; \ + add %scratch, 1, %scratch; \ + st %scratch, [%cur_reg + THREAD_W_SAVED]; + +#ifdef __SMP__ +#define LOAD_CURRENT(dest_reg, idreg) \ + rd %tbr, %idreg; \ + srl %idreg, 10, %idreg; \ + and %idreg, 0xc, %idreg; \ + sethi %hi(C_LABEL(current_set)), %dest_reg; \ + or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ + add %dest_reg, %idreg, %idreg; \ + ld [%idreg], %dest_reg; +#else +#define LOAD_CURRENT(dest_reg, idreg) \ + sethi %hi(C_LABEL(current_set)), %idreg; \ + ld [%idreg + %lo(C_LABEL(current_set))], %dest_reg; +#endif + +#endif /* !(_SPARC_WINMACRO_H) */ |