diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-18 19:49:58 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-18 19:49:58 +0000 |
commit | d348152c6db2646b5de8a40968c60c267c76bc3d (patch) | |
tree | a125d1523c9699f519c87976dbb76bef7f3a4b1b /sys/arch | |
parent | 7b95461118d83a8f536104debf9493e89f79d1cf (diff) |
More includes from NetBSD.
No modifications.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/include/asm.h | 157 | ||||
-rw-r--r-- | sys/arch/sparc64/include/bus.h | 1560 | ||||
-rw-r--r-- | sys/arch/sparc64/include/ctlreg.h | 1133 | ||||
-rw-r--r-- | sys/arch/sparc64/include/frame.h | 134 | ||||
-rw-r--r-- | sys/arch/sparc64/include/trap.h | 152 |
5 files changed, 3136 insertions, 0 deletions
diff --git a/sys/arch/sparc64/include/asm.h b/sys/arch/sparc64/include/asm.h new file mode 100644 index 00000000000..6ff0de358d5 --- /dev/null +++ b/sys/arch/sparc64/include/asm.h @@ -0,0 +1,157 @@ +/* $NetBSD: asm.h,v 1.15 2000/08/02 22:24:39 eeh Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ASM_H_ +#define _ASM_H_ + +#ifndef _LOCORE +#define _LOCORE +#endif +#include <machine/frame.h> + +#ifdef __arch64__ +#ifndef __ELF__ +#define __ELF__ +#endif +#endif + +/* Pull in CCFSZ, CC64FSZ, and BIAS from frame.h */ +#ifndef _LOCORE +#define _LOCORE +#endif +#include <machine/frame.h> + +#ifdef __ELF__ +#define _C_LABEL(name) name +#else +#ifdef __STDC__ +#define _C_LABEL(name) _ ## name +#else +#define _C_LABEL(name) _/**/name +#endif +#endif +#define _ASM_LABEL(name) name + +#ifdef PIC +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. Using the temporary enables us + * to work without a stack frame (doing so requires saving %o7) . + */ +#define PIC_PROLOGUE(dest,tmp) \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + rd %pc, tmp; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ + add dest,tmp,dest + +/* + * PICCY_SET() does the equivalent of a `set var, %dest' instruction in + * a PIC-like way, but without involving the Global Offset Table. This + * only works for VARs defined in the same file *and* in the text segment. + */ +#define PICCY_SET(var,dest,tmp) \ + 3: rd %pc, tmp; add tmp,(var-3b),dest +#else +#define PIC_PROLOGUE(dest,tmp) +#define PICCY_OFFSET(var,dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY(name) \ + .align 4; .globl name; .proc 1; FTYPE(name); name: + +#ifdef GPROF +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)); _PROF_PROLOGUE +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define RODATA(name) .align 4; .text; .globl _C_LABEL(name); \ + OTYPE(_C_LABEL(name)); _C_LABEL(name): + + +#define ASMSTR .asciz + +#define RCSID(name) .asciz name + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif + +/* + * WARN_REFERENCES: create a warning if the specified symbol is referenced. + */ +#ifdef __ELF__ +#ifdef __STDC__ +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning. ## _sym ; .ascii _msg ; .text +#else +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning./**/_sym ; .ascii _msg ; .text +#endif /* __STDC__ */ +#else +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ +#endif /* __ELF__ */ + +#endif /* _ASM_H_ */ diff --git a/sys/arch/sparc64/include/bus.h b/sys/arch/sparc64/include/bus.h new file mode 100644 index 00000000000..104c67c4598 --- /dev/null +++ b/sys/arch/sparc64/include/bus.h @@ -0,0 +1,1560 @@ +/* $NetBSD: bus.h,v 1.28 2001/07/19 15:32:19 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997-1999 Eduardo E. Horvath. All rights reserved. + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SPARC_BUS_H_ +#define _SPARC_BUS_H_ + +#include <machine/types.h> +#include <machine/ctlreg.h> + +/* + * Debug hooks + */ + +#define BSDB_ACCESS 0x01 +#define BSDB_MAP 0x02 +extern int bus_space_debug; + +/* + * UPA and SBUS spaces are non-cached and big endian + * (except for RAM and PROM) + * + * PCI spaces are non-cached and little endian + */ + +enum bus_type { + UPA_BUS_SPACE, + SBUS_BUS_SPACE, + PCI_CONFIG_BUS_SPACE, + PCI_IO_BUS_SPACE, + PCI_MEMORY_BUS_SPACE, + LAST_BUS_SPACE +}; +extern int bus_type_asi[]; +extern int bus_stream_asi[]; +/* For backwards compatibility */ +#define SPARC_BUS_SPACE UPA_BUS_SPACE + +#define __BUS_SPACE_HAS_STREAM_METHODS 1 + +/* + * Bus address and size types + */ +typedef u_int64_t bus_space_handle_t; +typedef enum bus_type bus_type_t; +typedef u_int64_t bus_addr_t; +typedef u_int64_t bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +typedef struct sparc_bus_space_tag *bus_space_tag_t; + +struct sparc_bus_space_tag { + void *cookie; + bus_space_tag_t parent; + int type; + + int (*sparc_bus_map) __P(( + bus_space_tag_t, + bus_type_t, + bus_addr_t, + bus_size_t, + int, /*flags*/ + vaddr_t, /*preferred vaddr*/ + bus_space_handle_t *)); + int (*sparc_bus_unmap) __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t)); + int (*sparc_bus_subregion) __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, /*offset*/ + bus_size_t, /*size*/ + bus_space_handle_t *)); + + void (*sparc_bus_barrier) __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, /*offset*/ + bus_size_t, /*size*/ + int)); /*flags*/ + + int (*sparc_bus_mmap) __P(( + bus_space_tag_t, + bus_type_t, /**/ + bus_addr_t, /**/ + int, /*flags*/ + bus_space_handle_t *)); + + void *(*sparc_intr_establish) __P(( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + int (*) __P((void *)), /*handler*/ + void *)); /*handler arg*/ + +}; + +#if 0 +/* + * The following macro could be used to generate the bus_space*() functions + * but it uses a gcc extension and is ANSI-only. +#define PROTO_bus_space_xxx __P((bus_space_tag_t t, ...)) +#define RETURNTYPE_bus_space_xxx void * +#define BUSFUN(name, returntype, t, args...) \ + __inline__ RETURNTYPE_##name \ + bus_##name PROTO_##name \ + { \ + while (t->sparc_##name == NULL) \ + t = t->parent; \ + return (*(t)->sparc_##name)(t, args); \ + } + */ +#endif + +/* + * Bus space function prototypes. + */ +static int bus_space_map __P(( + bus_space_tag_t, + bus_addr_t, + bus_size_t, + int, /*flags*/ + bus_space_handle_t *)); +static int bus_space_map2 __P(( + bus_space_tag_t, + bus_type_t, + bus_addr_t, + bus_size_t, + int, /*flags*/ + vaddr_t, /*preferred vaddr*/ + bus_space_handle_t *)); +static int bus_space_unmap __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t)); +static int bus_space_subregion __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + bus_space_handle_t *)); +static void bus_space_barrier __P(( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + int)); +static int bus_space_mmap __P(( + bus_space_tag_t, + bus_type_t, /**/ + bus_addr_t, /**/ + int, /*flags*/ + bus_space_handle_t *)); +static void *bus_intr_establish __P(( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + int (*) __P((void *)), /*handler*/ + void *)); /*handler arg*/ + + +/* This macro finds the first "upstream" implementation of method `f' */ +#define _BS_CALL(t,f) \ + while (t->f == NULL) \ + t = t->parent; \ + return (*(t)->f) + +__inline__ int +bus_space_map(t, a, s, f, hp) + bus_space_tag_t t; + bus_addr_t a; + bus_size_t s; + int f; + bus_space_handle_t *hp; +{ + _BS_CALL(t, sparc_bus_map)((t), 0, (a), (s), (f), 0, (hp)); +} + +__inline__ int +bus_space_map2(t, bt, a, s, f, v, hp) + bus_space_tag_t t; + bus_type_t bt; + bus_addr_t a; + bus_size_t s; + int f; + vaddr_t v; + bus_space_handle_t *hp; +{ + _BS_CALL(t, sparc_bus_map)(t, bt, a, s, f, v, hp); +} + +__inline__ int +bus_space_unmap(t, h, s) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t s; +{ + _BS_CALL(t, sparc_bus_unmap)(t, h, s); +} + +__inline__ int +bus_space_subregion(t, h, o, s, hp) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o; + bus_size_t s; + bus_space_handle_t *hp; +{ + _BS_CALL(t, sparc_bus_subregion)(t, h, o, s, hp); +} + +__inline__ int +bus_space_mmap(t, bt, a, f, hp) + bus_space_tag_t t; + bus_type_t bt; + bus_addr_t a; + int f; + bus_space_handle_t *hp; +{ + _BS_CALL(t, sparc_bus_mmap)(t, bt, a, f, hp); +} + +__inline__ void * +bus_intr_establish(t, p, l, f, h, a) + bus_space_tag_t t; + int p; + int l; + int f; + int (*h)__P((void *)); + void *a; +{ + _BS_CALL(t, sparc_intr_establish)(t, p, l, f, h, a); +} + +__inline__ void +bus_space_barrier(t, h, o, s, f) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o; + bus_size_t s; + int f; +{ + _BS_CALL(t, sparc_bus_barrier)(t, h, o, s, f); +} + + +#if 0 +int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp)); +void bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size)); +#endif + +/* flags for bus space map functions */ +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_READONLY 0x0004 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 +#define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */ +#define BUS_SPACE_MAP_BUS2 0x0200 +#define BUS_SPACE_MAP_BUS3 0x0400 +#define BUS_SPACE_MAP_BUS4 0x0800 + + +/* flags for intr_establish() */ +#define BUS_INTR_ESTABLISH_FASTTRAP 1 +#define BUS_INTR_ESTABLISH_SOFTINTR 2 + +/* flags for bus_space_barrier() */ +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +/* + * Device space probe assistant. + * The optional callback function's arguments are: + * the temporary virtual address + * the passed `arg' argument + */ +int bus_space_probe __P(( + bus_space_tag_t, + bus_type_t, + bus_addr_t, + bus_size_t, /* probe size */ + size_t, /* offset */ + int, /* flags */ + int (*) __P((void *, void *)), /* callback function */ + void *)); /* callback arg */ + + +/* + * u_intN_t bus_space_read_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset)); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ +#ifndef BUS_SPACE_DEBUG +#define bus_space_read_1(t, h, o) \ + lduba((h) + (o), bus_type_asi[(t)->type]) + +#define bus_space_read_2(t, h, o) \ + lduha((h) + (o), bus_type_asi[(t)->type]) + +#define bus_space_read_4(t, h, o) \ + lda((h) + (o), bus_type_asi[(t)->type]) + +#define bus_space_read_8(t, h, o) \ + ldxa((h) + (o), bus_type_asi[(t)->type]) +#else +#define bus_space_read_1(t, h, o) ({ \ + unsigned char __bv = \ + lduba((h) + (o), bus_type_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr1(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (unsigned int) __bv); \ + __bv; }) + +#define bus_space_read_2(t, h, o) ({ \ + unsigned short __bv = \ + lduha((h) + (o), bus_type_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr2(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (unsigned int)__bv); \ + __bv; }) + +#define bus_space_read_4(t, h, o) ({ \ + unsigned int __bv = \ + lda((h) + (o), bus_type_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr4(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], __bv); \ + __bv; }) + +#define bus_space_read_8(t, h, o) ({ \ + u_int64_t __bv = \ + ldxa((h) + (o), bus_type_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr8(%llx + %llx, %x) -> %llx\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], __bv); \ + __bv; }) +#endif +/* + * void bus_space_read_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + +#define bus_space_read_multi_1(t, h, o, a, c) do { \ + int i = c; \ + u_int8_t *p = (u_int8_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_1(t, h, o); \ +} while (0) + +#define bus_space_read_multi_2(t, h, o, a, c) do { \ + int i = c; \ + u_int16_t *p = (u_int16_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_2(t, h, o); \ +} while (0) + +#define bus_space_read_multi_4(t, h, o, a, c) do { \ + int i = c; \ + u_int32_t *p = (u_int32_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_4(t, h, o); \ +} while (0) + +#define bus_space_read_multi_8(t, h, o, a, c) do { \ + int i = c; \ + u_int64_t *p = (u_int64_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_8(t, h, o); \ +} while (0) + +/* + * void bus_space_write_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value)); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ +#ifndef BUS_SPACE_DEBUG +#define bus_space_write_1(t, h, o, v) \ + ((void)(stba((h) + (o), bus_type_asi[(t)->type], (v)))) + +#define bus_space_write_2(t, h, o, v) \ + ((void)(stha((h) + (o), bus_type_asi[(t)->type], (v)))) + +#define bus_space_write_4(t, h, o, v) \ + ((void)(sta((h) + (o), bus_type_asi[(t)->type], (v)))) + +#define bus_space_write_8(t, h, o, v) \ + ((void)(stxa((h) + (o), bus_type_asi[(t)->type], (v)))) +#else +#define bus_space_write_1(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw1(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (unsigned int) v); \ + ((void)(stba((h) + (o), bus_type_asi[(t)->type], (v)))); }) + +#define bus_space_write_2(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw2(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (unsigned int) v); \ + ((void)(stha((h) + (o), bus_type_asi[(t)->type], (v)))); }) + +#define bus_space_write_4(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw4(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (unsigned int) v); \ + ((void)(sta((h) + (o), bus_type_asi[(t)->type], (v)))); }) + +#define bus_space_write_8(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw8(%llx + %llx, %x) <- %llx\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_type_asi[(t)->type], (u_int64_t) v); \ + ((void)(stxa((h) + (o), bus_type_asi[(t)->type], (v)))); }) +#endif +/* + * void bus_space_write_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + +#define bus_space_write_multi_1(t, h, o, a, c) do { \ + int i = c; \ + u_int8_t *p = (u_int8_t *)a; \ + while (i-- > 0) \ + bus_space_write_1(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_2(t, h, o, a, c) do { \ + int i = c; \ + u_int16_t *p = (u_int16_t *)a; \ + while (i-- > 0) \ + bus_space_write_2(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_4(t, h, o, a, c) do { \ + int i = c; \ + u_int32_t *p = (u_int32_t *)a; \ + while (i-- > 0) \ + bus_space_write_4(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_8(t, h, o, a, c) do { \ + int i = c; \ + u_int64_t *p = (u_int64_t *)a; \ + while (i-- > 0) \ + bus_space_write_8(t, h, o, *p++); \ +} while (0) + +/* + * void bus_space_set_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + +#define bus_space_set_multi_1(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_1(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_2(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_2(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_4(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_4(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_8(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_8(t, h, o, v); \ +} while (0) + +/* + * void bus_space_read_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_read_region_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int8_t *, + bus_size_t)); +static void bus_space_read_region_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int16_t *, + bus_size_t)); +static void bus_space_read_region_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int32_t *, + bus_size_t)); +static void bus_space_read_region_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int64_t *, + bus_size_t)); + +static __inline__ void +bus_space_read_region_1(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int8_t *a; +{ + for (; c; a++, c--, o++) + *a = bus_space_read_1(t, h, o); +} +static __inline__ void +bus_space_read_region_2(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int16_t *a; +{ + for (; c; a++, c--, o+=2) + *a = bus_space_read_2(t, h, o); + } +static __inline__ void +bus_space_read_region_4(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int32_t *a; +{ + for (; c; a++, c--, o+=4) + *a = bus_space_read_4(t, h, o); +} +static __inline__ void +bus_space_read_region_8(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int64_t *a; +{ + for (; c; a++, c--, o+=8) + *a = bus_space_read_8(t, h, o); +} + +/* + * void bus_space_write_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_write_region_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int8_t *, + bus_size_t)); +static void bus_space_write_region_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int16_t *, + bus_size_t)); +static void bus_space_write_region_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int32_t *, + bus_size_t)); +static void bus_space_write_region_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int64_t *, + bus_size_t)); +static __inline__ void +bus_space_write_region_1(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int8_t *a; +{ + for (; c; a++, c--, o++) + bus_space_write_1(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_2(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int16_t *a; +{ + for (; c; a++, c--, o+=2) + bus_space_write_2(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_4(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int32_t *a; +{ + for (; c; a++, c--, o+=4) + bus_space_write_4(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_8(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int64_t *a; +{ + for (; c; a++, c--, o+=8) + bus_space_write_8(t, h, o, *a); +} + + +/* + * void bus_space_set_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_set_region_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int8_t, + bus_size_t)); +static void bus_space_set_region_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int16_t, + bus_size_t)); +static void bus_space_set_region_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int32_t, + bus_size_t)); +static void bus_space_set_region_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int64_t, + bus_size_t)); + +static __inline__ void +bus_space_set_region_1(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int8_t v; +{ + for (; c; c--, o++) + bus_space_write_1(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_2(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int16_t v; +{ + for (; c; c--, o+=2) + bus_space_write_2(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_4(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int32_t v; +{ + for (; c; c--, o+=4) + bus_space_write_4(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_8(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int64_t v; +{ + for (; c; c--, o+=8) + bus_space_write_8(t, h, o, v); +} + + +/* + * void bus_space_copy_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * bus_size_t count)); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ +static void bus_space_copy_region_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); + + +static __inline__ void +bus_space_copy_region_1(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1++, o2++) + bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_2(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=2, o2+=2) + bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_4(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=4, o2+=4) + bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_8(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=8, o2+=8) + bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); +} + +/* + * u_intN_t bus_space_read_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset)); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ +#ifndef BUS_SPACE_DEBUG +#define bus_space_read_stream_1(t, h, o) \ + lduba((h) + (o), bus_stream_asi[(t)->type]) + +#define bus_space_read_stream_2(t, h, o) \ + lduha((h) + (o), bus_stream_asi[(t)->type]) + +#define bus_space_read_stream_4(t, h, o) \ + lda((h) + (o), bus_stream_asi[(t)->type]) + +#define bus_space_read_stream_8(t, h, o) \ + ldxa((h) + (o), bus_stream_asi[(t)->type]) +#else +#define bus_space_read_stream_1(t, h, o) ({ \ + unsigned char __bv = \ + lduba((h) + (o), bus_stream_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr1(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (unsigned int) __bv); \ + __bv; }) + +#define bus_space_read_stream_2(t, h, o) ({ \ + unsigned short __bv = \ + lduha((h) + (o), bus_stream_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr2(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (unsigned int)__bv); \ + __bv; }) + +#define bus_space_read_stream_4(t, h, o) ({ \ + unsigned int __bv = \ + lda((h) + (o), bus_stream_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr4(%llx + %llx, %x) -> %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], __bv); \ + __bv; }) + +#define bus_space_read_stream_8(t, h, o) ({ \ + u_int64_t __bv = \ + ldxa((h) + (o), bus_stream_asi[(t)->type]); \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsr8(%llx + %llx, %x) -> %llx\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], __bv); \ + __bv; }) +#endif +/* + * void bus_space_read_multi_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + +#define bus_space_read_multi_stream_1(t, h, o, a, c) do { \ + int i = c; \ + u_int8_t *p = (u_int8_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_stream_1(t, h, o); \ +} while (0) + +#define bus_space_read_multi_stream_2(t, h, o, a, c) do { \ + int i = c; \ + u_int16_t *p = (u_int16_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_stream_2(t, h, o); \ +} while (0) + +#define bus_space_read_multi_stream_4(t, h, o, a, c) do { \ + int i = c; \ + u_int32_t *p = (u_int32_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_stream_4(t, h, o); \ +} while (0) + +#define bus_space_read_multi_stream_8(t, h, o, a, c) do { \ + int i = c; \ + u_int64_t *p = (u_int64_t *)a; \ + while (i-- > 0) \ + *p++ = bus_space_read_stream_8(t, h, o); \ +} while (0) + +/* + * void bus_space_write_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value)); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ +#ifndef BUS_SPACE_DEBUG +#define bus_space_write_stream_1(t, h, o, v) \ + ((void)(stba((h) + (o), bus_stream_asi[(t)->type], (v)))) + +#define bus_space_write_stream_2(t, h, o, v) \ + ((void)(stha((h) + (o), bus_stream_asi[(t)->type], (v)))) + +#define bus_space_write_stream_4(t, h, o, v) \ + ((void)(sta((h) + (o), bus_stream_asi[(t)->type], (v)))) + +#define bus_space_write_stream_8(t, h, o, v) \ + ((void)(stxa((h) + (o), bus_stream_asi[(t)->type], (v)))) +#else +#define bus_space_write_stream_1(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw1(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (unsigned int) v); \ + ((void)(stba((h) + (o), bus_stream_asi[(t)->type], (v)))); }) + +#define bus_space_write_stream_2(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw2(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (unsigned int) v); \ + ((void)(stha((h) + (o), bus_stream_asi[(t)->type], (v)))); }) + +#define bus_space_write_stream_4(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw4(%llx + %llx, %x) <- %x\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (unsigned int) v); \ + ((void)(sta((h) + (o), bus_stream_asi[(t)->type], (v)))); }) + +#define bus_space_write_stream_8(t, h, o, v) ({ \ + if (bus_space_debug & BSDB_ACCESS) \ + printf("bsw8(%llx + %llx, %x) <- %llx\n", (u_int64_t)(h), \ + (u_int64_t)(o), \ + bus_stream_asi[(t)->type], (u_int64_t) v); \ + ((void)(stxa((h) + (o), bus_stream_asi[(t)->type], (v)))); }) +#endif +/* + * void bus_space_write_multi_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + +#define bus_space_write_multi_stream_1(t, h, o, a, c) do { \ + int i = c; \ + u_int8_t *p = (u_int8_t *)a; \ + while (i-- > 0) \ + bus_space_write_stream_1(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_stream_2(t, h, o, a, c) do { \ + int i = c; \ + u_int16_t *p = (u_int16_t *)a; \ + while (i-- > 0) \ + bus_space_write_stream_2(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_stream_4(t, h, o, a, c) do { \ + int i = c; \ + u_int32_t *p = (u_int32_t *)a; \ + while (i-- > 0) \ + bus_space_write_stream_4(t, h, o, *p++); \ +} while (0) + +#define bus_space_write_multi_stream_8(t, h, o, a, c) do { \ + int i = c; \ + u_int64_t *p = (u_int64_t *)a; \ + while (i-- > 0) \ + bus_space_write_stream_8(t, h, o, *p++); \ +} while (0) + +/* + * void bus_space_set_multi_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + +#define bus_space_set_multi_stream_1(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_stream_1(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_stream_2(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_stream_2(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_stream_4(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_stream_4(t, h, o, v); \ +} while (0) + +#define bus_space_set_multi_stream_8(t, h, o, v, c) do { \ + int i = c; \ + while (i-- > 0) \ + bus_space_write_stream_8(t, h, o, v); \ +} while (0) + +/* + * void bus_space_read_region_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_read_region_stream_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int8_t *, + bus_size_t)); +static void bus_space_read_region_stream_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int16_t *, + bus_size_t)); +static void bus_space_read_region_stream_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int32_t *, + bus_size_t)); +static void bus_space_read_region_stream_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + u_int64_t *, + bus_size_t)); + +static __inline__ void +bus_space_read_region_stream_1(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int8_t *a; +{ + for (; c; a++, c--, o++) + *a = bus_space_read_stream_1(t, h, o); +} +static __inline__ void +bus_space_read_region_stream_2(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int16_t *a; +{ + for (; c; a++, c--, o+=2) + *a = bus_space_read_stream_2(t, h, o); + } +static __inline__ void +bus_space_read_region_stream_4(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int32_t *a; +{ + for (; c; a++, c--, o+=4) + *a = bus_space_read_stream_4(t, h, o); +} +static __inline__ void +bus_space_read_region_stream_8(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + u_int64_t *a; +{ + for (; c; a++, c--, o+=8) + *a = bus_space_read_stream_8(t, h, o); +} + +/* + * void bus_space_write_region_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_write_region_stream_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int8_t *, + bus_size_t)); +static void bus_space_write_region_stream_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int16_t *, + bus_size_t)); +static void bus_space_write_region_stream_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int32_t *, + bus_size_t)); +static void bus_space_write_region_stream_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int64_t *, + bus_size_t)); +static __inline__ void +bus_space_write_region_stream_1(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int8_t *a; +{ + for (; c; a++, c--, o++) + bus_space_write_stream_1(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_stream_2(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int16_t *a; +{ + for (; c; a++, c--, o+=2) + bus_space_write_stream_2(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_stream_4(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int32_t *a; +{ + for (; c; a++, c--, o+=4) + bus_space_write_stream_4(t, h, o, *a); +} + +static __inline__ void +bus_space_write_region_stream_8(t, h, o, a, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int64_t *a; +{ + for (; c; a++, c--, o+=8) + bus_space_write_stream_8(t, h, o, *a); +} + + +/* + * void bus_space_set_region_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t off, + * u_intN_t *addr, bus_size_t count)); + * + */ +static void bus_space_set_region_stream_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int8_t, + bus_size_t)); +static void bus_space_set_region_stream_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int16_t, + bus_size_t)); +static void bus_space_set_region_stream_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int32_t, + bus_size_t)); +static void bus_space_set_region_stream_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + const u_int64_t, + bus_size_t)); + +static __inline__ void +bus_space_set_region_stream_1(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int8_t v; +{ + for (; c; c--, o++) + bus_space_write_stream_1(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_stream_2(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int16_t v; +{ + for (; c; c--, o+=2) + bus_space_write_stream_2(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_stream_4(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int32_t v; +{ + for (; c; c--, o+=4) + bus_space_write_stream_4(t, h, o, v); +} + +static __inline__ void +bus_space_set_region_stream_8(t, h, o, v, c) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t o, c; + const u_int64_t v; +{ + for (; c; c--, o+=8) + bus_space_write_stream_8(t, h, o, v); +} + + +/* + * void bus_space_copy_region_stream_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * bus_size_t count)); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ +static void bus_space_copy_region_stream_1 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_stream_2 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_stream_4 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); +static void bus_space_copy_region_stream_8 __P((bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_space_handle_t, + bus_size_t, + bus_size_t)); + + +static __inline__ void +bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1++, o2++) + bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=2, o2+=2) + bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=4, o2+=4) + bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2, o2)); +} + +static __inline__ void +bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c) + bus_space_tag_t t; + bus_space_handle_t h1, h2; + bus_size_t o1, o2; + bus_size_t c; +{ + for (; c; c--, o1+=8, o2+=8) + bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2)); +} + + +#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ +#define BUS_DMA_NOWRITE 0x008 /* I suppose the following two should default on */ +#define BUS_DMA_BUS1 0x010 +#define BUS_DMA_BUS2 0x020 +#define BUS_DMA_BUS3 0x040 +#define BUS_DMA_BUS4 0x080 +#define BUS_DMA_STREAMING 0x100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x400 /* mapping is memory -> device only */ + + +#define BUS_DMA_NOCACHE BUS_DMA_BUS1 +#define BUS_DMA_DVMA BUS_DMA_BUS2 /* Don't bother with alignment */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +typedef struct sparc_bus_dma_tag *bus_dma_tag_t; +typedef struct sparc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct sparc_bus_dma_segment { + bus_addr_t ds_addr; /* DVMA address */ + bus_size_t ds_len; /* length of transfer */ + bus_size_t _ds_boundary; /* don't cross this */ + bus_size_t _ds_align; /* align to this */ + void *_ds_mlist; /* XXX - dmamap_alloc'ed pages */ +}; +typedef struct sparc_bus_dma_segment bus_dma_segment_t; + + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ +struct sparc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + struct sparc_bus_dma_tag* _parent; + + /* + * DMA mapping methods. + */ + int (*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *)); + void (*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t)); + int (*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); + int (*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); + int (*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); + int (*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + void (*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t)); + void (*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int)); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int)); + void (*_dmamem_free) __P((bus_dma_tag_t, + bus_dma_segment_t *, int)); + int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int)); + void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t)); + paddr_t (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int)); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct sparc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use my machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_segcnt; /* number of segs this map can map */ + int _dm_flags; /* misc. flags */ +#define _DM_TYPE_LOAD 0 +#define _DM_TYPE_SEGS 1 +#define _DM_TYPE_UIO 2 +#define _DM_TYPE_MBUF 3 + int _dm_type; /* type of mapping: raw, uio, mbuf, etc */ + void *_dm_source; /* source mbuf, uio, etc. needed for unload */////////////////////// + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#ifdef _SPARC_BUS_DMA_PRIVATE +int _bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *)); +void _bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t)); +int _bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); +int _bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); +int _bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); +int _bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); +void _bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); +void _bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int)); + +int _bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags)); +void _bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs)); +int _bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags)); +void _bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva, + size_t size)); +paddr_t _bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags)); + +int _bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + vaddr_t low, vaddr_t high)); +#endif /* _SPARC_BUS_DMA_PRIVATE */ + +#endif /* _SPARC_BUS_H_ */ diff --git a/sys/arch/sparc64/include/ctlreg.h b/sys/arch/sparc64/include/ctlreg.h new file mode 100644 index 00000000000..d9368450c8e --- /dev/null +++ b/sys/arch/sparc64/include/ctlreg.h @@ -0,0 +1,1133 @@ +/* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */ + +/* + * Copyright (c) 1996-2001 Eduardo Horvath + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Sun 4u control registers. (includes address space definitions + * and some registers in control space). + */ + +/* + * The Alternate address spaces. + * + * 0x00-0x7f are privileged + * 0x80-0xff can be used by users + */ + +#define ASI_LITTLE 0x08 /* This bit should make an ASI little endian */ + +#define ASI_NUCLEUS 0x04 /* [4u] kernel address space */ +#define ASI_NUCLEUS_LITTLE 0x0c /* [4u] kernel address space, little endian */ + +#define ASI_AS_IF_USER_PRIMARY 0x10 /* [4u] primary user address space */ +#define ASI_AS_IF_USER_SECONDARY 0x11 /* [4u] secondary user address space */ + +#define ASI_PHYS_CACHED 0x14 /* [4u] MMU bypass to main memory */ +#define ASI_PHYS_NON_CACHED 0x15 /* [4u] MMU bypass to I/O location */ + +#define ASI_AS_IF_USER_PRIMARY_LITTLE 0x18 /* [4u] primary user address space, little endian */ +#define ASI_AS_IF_USER_SECONDARY_LITTIE 0x19 /* [4u] secondary user address space, little endian */ + +#define ASI_PHYS_CACHED_LITTLE 0x1c /* [4u] MMU bypass to main memory, little endian */ +#define ASI_PHYS_NON_CACHED_LITTLE 0x1d /* [4u] MMU bypass to I/O location, little endian */ + +#define ASI_NUCLEUS_QUAD_LDD 0x24 /* [4u] use w/LDDA to load 128-bit item */ +#define ASI_NUCLEUS_QUAD_LDD_LITTLE 0x2c /* [4u] use w/LDDA to load 128-bit item, little endian */ + +#define ASI_FLUSH_D_PAGE_PRIMARY 0x38 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_D_PAGE_SECONDARY 0x39 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_D_CTX_PRIMARY 0x3a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_D_CTX_SECONDARY 0x3b /* [4u] flush D-cache context using secondary context */ + +#define ASI_LSU_CONTROL_REGISTER 0x45 /* [4u] load/store unit control register */ + +#define ASI_DCACHE_DATA 0x46 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_DCACHE_TAG 0x47 /* [4u] diagnostic access to D-cache tag RAM */ + +#define ASI_INTR_DISPATCH_STATUS 0x48 /* [4u] interrupt dispatch status register */ +#define ASI_INTR_RECEIVE 0x49 /* [4u] interrupt receive status register */ +#define ASI_MID_REG 0x4a /* [4u] hardware config and MID */ +#define ASI_ERROR_EN_REG 0x4b /* [4u] asynchronous error enables */ +#define ASI_AFSR 0x4c /* [4u] asynchronous fault status register */ +#define ASI_AFAR 0x4d /* [4u] asynchronous fault address register */ + +#define ASI_ICACHE_DATA 0x66 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_ICACHE_TAG 0x67 /* [4u] diagnostic access to D-cache tag RAM */ +#define ASI_FLUSH_I_PAGE_PRIMARY 0x68 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_I_PAGE_SECONDARY 0x69 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_I_CTX_PRIMARY 0x6a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_I_CTX_SECONDARY 0x6b /* [4u] flush D-cache context using secondary context */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY 0x70 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY 0x71 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_ECACHE_DIAG 0x76 /* [4u] diag access to E-cache tag and data */ +#define ASI_DATAPATH_ERR_REG_WRITE 0x77 /* [4u] ASI is reused */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE 0x78 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE 0x79 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_INTERRUPT_RECEIVE_DATA 0x7f /* [4u] interrupt receive data registers {0,1,2} */ +#define ASI_DATAPATH_ERR_REG_READ 0x7f /* [4u] read access to datapath error registers (ASI reused) */ + +#define ASI_PRIMARY 0x80 /* [4u] primary address space */ +#define ASI_SECONDARY 0x81 /* [4u] secondary address space */ +#define ASI_PRIMARY_NOFAULT 0x82 /* [4u] primary address space, no fault */ +#define ASI_SECONDARY_NOFAULT 0x83 /* [4u] secondary address space, no fault */ + +#define ASI_PRIMARY_LITTLE 0x88 /* [4u] primary address space, little endian */ +#define ASI_SECONDARY_LITTLE 0x89 /* [4u] secondary address space, little endian */ +#define ASI_PRIMARY_NOFAULT_LITTLE 0x8a /* [4u] primary address space, no fault, little endian */ +#define ASI_SECONDARY_NOFAULT_LITTLE 0x8b /* [4u] secondary address space, no fault, little endian */ + +#define ASI_PST8_PRIMARY 0xc0 /* [VIS] Eight 8-bit partial store, primary */ +#define ASI_PST8_SECONDARY 0xc1 /* [VIS] Eight 8-bit partial store, secondary */ +#define ASI_PST16_PRIMARY 0xc2 /* [VIS] Four 16-bit partial store, primary */ +#define ASI_PST16_SECONDARY 0xc3 /* [VIS] Fout 16-bit partial store, secondary */ +#define ASI_PST32_PRIMARY 0xc4 /* [VIS] Two 32-bit partial store, primary */ +#define ASI_PST32_SECONDARY 0xc5 /* [VIS] Two 32-bit partial store, secondary */ + +#define ASI_PST8_PRIMARY_LITTLE 0xc8 /* [VIS] Eight 8-bit partial store, primary, little endian */ +#define ASI_PST8_SECONDARY_LITTLE 0xc9 /* [VIS] Eight 8-bit partial store, secondary, little endian */ +#define ASI_PST16_PRIMARY_LITTLE 0xca /* [VIS] Four 16-bit partial store, primary, little endian */ +#define ASI_PST16_SECONDARY_LITTLE 0xcb /* [VIS] Fout 16-bit partial store, secondary, little endian */ +#define ASI_PST32_PRIMARY_LITTLE 0xcc /* [VIS] Two 32-bit partial store, primary, little endian */ +#define ASI_PST32_SECONDARY_LITTLE 0xcd /* [VIS] Two 32-bit partial store, secondary, little endian */ + +#define ASI_FL8_PRIMARY 0xd0 /* [VIS] One 8-bit load/store floating, primary */ +#define ASI_FL8_SECONDARY 0xd1 /* [VIS] One 8-bit load/store floating, secondary */ +#define ASI_FL16_PRIMARY 0xd2 /* [VIS] One 16-bit load/store floating, primary */ +#define ASI_FL16_SECONDARY 0xd3 /* [VIS] One 16-bit load/store floating, secondary */ + +#define ASI_FL8_PRIMARY_LITTLE 0xd8 /* [VIS] One 8-bit load/store floating, primary, little endian */ +#define ASI_FL8_SECONDARY_LITTLE 0xd9 /* [VIS] One 8-bit load/store floating, secondary, little endian */ +#define ASI_FL16_PRIMARY_LITTLE 0xda /* [VIS] One 16-bit load/store floating, primary, little endian */ +#define ASI_FL16_SECONDARY_LITTLE 0xdb /* [VIS] One 16-bit load/store floating, secondary, little endian */ + +#define ASI_BLOCK_COMMIT_PRIMARY 0xe0 /* [4u] block store with commit, primary */ +#define ASI_BLOCK_COMMIT_SECONDARY 0xe1 /* [4u] block store with commit, secondary */ +#define ASI_BLOCK_PRIMARY 0xf0 /* [4u] block load/store, primary */ +#define ASI_BLOCK_SECONDARY 0xf1 /* [4u] block load/store, secondary */ +#define ASI_BLOCK_PRIMARY_LITTLE 0xf8 /* [4u] block load/store, primary, little endian */ +#define ASI_BLOCK_SECONDARY_LITTLE 0xf9 /* [4u] block load/store, secondary, little endian */ + + +/* + * These are the shorter names used by Solaris + */ + +#define ASI_N ASI_NUCLEUS +#define ASI_NL ASI_NUCLEUS_LITTLE +#define ASI_AIUP ASI_AS_IF_USER_PRIMARY +#define ASI_AIUS ASI_AS_IF_USER_SECONDARY +#define ASI_AIUPL ASI_AS_IF_USER_PRIMARY_LITTLE +#define ASI_AIUSL ASI_AS_IF_USER_SECONDARY_LITTLE +#define ASI_P ASI_PRIMARY +#define ASI_S ASI_SECONDARY +#define ASI_PNF ASI_PRIMARY_NOFAULT +#define ASI_SNF ASI_SECONDARY_NOFAULT +#define ASI_PL ASI_PRIMARY_LITTLE +#define ASI_SL ASI_SECONDARY_LITTLE +#define ASI_PNFL ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SNFL ASI_SECONDARY_NOFAULT_LITTLE +#define ASI_FL8_P ASI_FL8_PRIMARY +#define ASI_FL8_S ASI_FL8_SECONDARY +#define ASI_FL16_P ASI_FL16_PRIMARY +#define ASI_FL16_S ASI_FL16_SECONDARY +#define ASI_FL8_PL ASI_FL8_PRIMARY_LITTLE +#define ASI_FL8_SL ASI_FL8_SECONDARY_LITTLE +#define ASI_FL16_PL ASI_FL16_PRIMARY_LITTLE +#define ASI_FL16_SL ASI_FL16_SECONDARY_LITTLE +#define ASI_BLK_AIUP ASI_BLOCK_AS_IF_USER_PRIMARY +#define ASI_BLK_AIUPL ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE +#define ASI_BLK_AIUS ASI_BLOCK_AS_IF_USER_SECONDARY +#define ASI_BLK_AIUSL ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE +#define ASI_BLK_COMMIT_P ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_PRIMARY ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_S ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_COMMIT_SECONDARY ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_P ASI_BLOCK_PRIMARY +#define ASI_BLK_PL ASI_BLOCK_PRIMARY_LITTLE +#define ASI_BLK_S ASI_BLOCK_SECONDARY +#define ASI_BLK_SL ASI_BLOCK_SECONDARY_LITTLE + +/* Alternative spellings */ +#define ASI_PRIMARY_NO_FAULT ASI_PRIMARY_NOFAULT +#define ASI_PRIMARY_NO_FAULT_LITTLE ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SECONDARY_NO_FAULT ASI_SECONDARY_NOFAULT +#define ASI_SECONDARY_NO_FAULT_LITTLE ASI_SECONDARY_NOFAULT_LITTLE + +#define PHYS_ASI(x) (((x) | 0x08) == 0x1c) +#define LITTLE_ASI(x) ((x) & ASI_LITTLE) + +/* + * The following are 4u control registers + */ + + +/* Get the CPU's UPAID */ +#define UPA_CR_MID(x) (((x)>>17)&0x1f) +#define CPU_UPAID UPA_CR_MID(ldxa(0, ASI_MID_REG)) + +/* + * [4u] MMU and Cache Control Register (MCCR) + * use ASI = 0x45 + */ +#define ASI_MCCR ASI_LSU_CONTROL_REGISTER +#define MCCR 0x00 + +/* MCCR Bits and their meanings */ +#define MCCR_DMMU_EN 0x08 +#define MCCR_IMMU_EN 0x04 +#define MCCR_DCACHE_EN 0x02 +#define MCCR_ICACHE_EN 0x01 + + +/* + * MMU control registers + */ + +/* Choose an MMU */ +#define ASI_DMMU 0x58 +#define ASI_IMMU 0x50 + +/* Other assorted MMU ASIs */ +#define ASI_IMMU_8KPTR 0x51 +#define ASI_IMMU_64KPTR 0x52 +#define ASI_IMMU_DATA_IN 0x54 +#define ASI_IMMU_TLB_DATA 0x55 +#define ASI_IMMU_TLB_TAG 0x56 +#define ASI_DMMU_8KPTR 0x59 +#define ASI_DMMU_64KPTR 0x5a +#define ASI_DMMU_DATA_IN 0x5c +#define ASI_DMMU_TLB_DATA 0x5d +#define ASI_DMMU_TLB_TAG 0x5e + +/* + * The following are the control registers + * They work on both MMUs unless noted. + * + * Register contents are defined later on individual registers. + */ +#define TSB_TAG_TARGET 0x0 +#define TLB_DATA_IN 0x0 +#define CTX_PRIMARY 0x08 /* primary context -- DMMU only */ +#define CTX_SECONDARY 0x10 /* secondary context -- DMMU only */ +#define SFSR 0x18 +#define SFAR 0x20 /* fault address -- DMMU only */ +#define TSB 0x28 +#define TLB_TAG_ACCESS 0x30 +#define VIRTUAL_WATCHPOINT 0x38 +#define PHYSICAL_WATCHPOINT 0x40 + +/* Tag Target bits */ +#define TAG_TARGET_VA_MASK 0x03ffffffffffffffffLL +#define TAG_TARGET_VA(x) (((x)<<22)&TAG_TARGET_VA_MASK) +#define TAG_TARGET_CONTEXT(x) ((x)>>48) +#define TAG_TARGET(c,v) ((((uint64_t)c)<<48)|(((uint64_t)v)&TAG_TARGET_VA_MASK)) + +/* SFSR bits for both D_SFSR and I_SFSR */ +#define SFSR_ASI(x) ((x)>>16) +#define SFSR_FT_VA_OOR_2 0x02000 /* IMMU: jumpl or return to unsupportd VA */ +#define SFSR_FT_VA_OOR_1 0x01000 /* fault at unsupported VA */ +#define SFSR_FT_NFO 0x00800 /* DMMU: Access to page marked NFO */ +#define SFSR_ILL_ASI 0x00400 /* DMMU: Illegal (unsupported) ASI */ +#define SFSR_FT_IO_ATOMIC 0x00200 /* DMMU: Atomic access to noncacheable page */ +#define SFSR_FT_ILL_NF 0x00100 /* DMMU: NF load or flush to page marked E (has side effects) */ +#define SFSR_FT_PRIV 0x00080 /* Privilege violation */ +#define SFSR_FT_E 0x00040 /* DMUU: value of E bit associated address */ +#define SFSR_CTXT(x) (((x)>>4)&0x3) +#define SFSR_CTXT_IS_PRIM(x) (SFSR_CTXT(x)==0x00) +#define SFSR_CTXT_IS_SECOND(x) (SFSR_CTXT(x)==0x01) +#define SFSR_CTXT_IS_NUCLEUS(x) (SFSR_CTXT(x)==0x02) +#define SFSR_PRIV 0x00008 /* value of PSTATE.PRIV for faulting access */ +#define SFSR_W 0x00004 /* DMMU: attempted write */ +#define SFSR_OW 0x00002 /* Overwrite; prev vault was still valid */ +#define SFSR_FV 0x00001 /* Fault is valid */ +#define SFSR_FT (SFSR_FT_VA_OOR_2|SFSR_FT_VA_OOR_1|SFSR_FT_NFO|SFSR_ILL_ASI|SFSR_FT_IO_ATOMIC|SFSR_FT_ILL_NF|SFSR_FT_PRIV) + +#if 0 +/* Old bits */ +#define SFSR_BITS "\40\16VAT\15VAD\14NFO\13ASI\12A\11NF\10PRIV\7E\6NUCLEUS\5SECONDCTX\4PRIV\3W\2OW\1FV" +#else +/* New bits */ +#define SFSR_BITS "\177\20" \ + "f\20\30ASI\0" "b\16VAT\0" "b\15VAD\0" "b\14NFO\0" "b\13ASI\0" "b\12A\0" "b\11NF\0" "b\10PRIV\0" \ + "b\7E\0" "b\6NUCLEUS\0" "b\5SECONDCTX\0" "b\4PRIV\0" "b\3W\0" "b\2OW\0" "b\1FV\0" +#endif + +/* ASFR bits */ +#define ASFR_ME 0x100000000LL +#define ASFR_PRIV 0x080000000LL +#define ASFR_ISAP 0x040000000LL +#define ASFR_ETP 0x020000000LL +#define ASFR_IVUE 0x010000000LL +#define ASFR_TO 0x008000000LL +#define ASFR_BERR 0x004000000LL +#define ASFR_LDP 0x002000000LL +#define ASFR_CP 0x001000000LL +#define ASFR_WP 0x000800000LL +#define ASFR_EDP 0x000400000LL +#define ASFR_UE 0x000200000LL +#define ASFR_CE 0x000100000LL +#define ASFR_ETS 0x0000f0000LL +#define ASFT_P_SYND 0x00000ffffLL + +#define AFSR_BITS "\177\20" \ + "b\40ME\0" "b\37PRIV\0" "b\36ISAP\0" "b\35ETP\0" \ + "b\34IVUE\0" "b\33TO\0" "b\32BERR\0" "b\31LDP\0" \ + "b\30CP\0" "b\27WP\0" "b\26EDP\0" "b\25UE\0" \ + "b\24CE\0" "f\20\4ETS\0" "f\0\20P_SYND\0" + +/* + * Here's the spitfire TSB control register bits. + * + * Each TSB entry is 16-bytes wide. The TSB must be size aligned + */ +#define TSB_SIZE_512 0x0 /* 8kB, etc. */ +#define TSB_SIZE_1K 0x01 +#define TSB_SIZE_2K 0x02 +#define TSB_SIZE_4K 0x03 +#define TSB_SIZE_8K 0x04 +#define TSB_SIZE_16K 0x05 +#define TSB_SIZE_32K 0x06 +#define TSB_SIZE_64K 0x07 +#define TSB_SPLIT 0x1000 +#define TSB_BASE 0xffffffffffffe000 + +/* TLB Tag Access bits */ +#define TLB_TAG_ACCESS_VA 0xffffffffffffe000 +#define TLB_TAG_ACCESS_CTX 0x0000000000001fff + +/* + * TLB demap registers. TTEs are defined in v9pte.h + * + * Use the address space to select between IMMU and DMMU. + * The address of the register selects which context register + * to read the ASI from. + * + * The data stored in the register is interpreted as the VA to + * use. The DEMAP_CTX_<> registers ignore the address and demap the + * entire ASI. + * + */ +#define ASI_IMMU_DEMAP 0x57 /* [4u] IMMU TLB demap */ +#define ASI_DMMU_DEMAP 0x5f /* [4u] IMMU TLB demap */ + +#define DEMAP_PAGE_NUCLEUS ((0x02)<<4) /* Demap page from kernel AS */ +#define DEMAP_PAGE_PRIMARY ((0x00)<<4) /* Demap a page from primary CTXT */ +#define DEMAP_PAGE_SECONDARY ((0x01)<<4) /* Demap page from secondary CTXT (DMMU only) */ +#define DEMAP_CTX_NUCLEUS ((0x06)<<4) /* Demap all of kernel CTXT */ +#define DEMAP_CTX_PRIMARY ((0x04)<<4) /* Demap all of primary CTXT */ +#define DEMAP_CTX_SECONDARY ((0x05)<<4) /* Demap all of secondary CTXT */ + +/* + * Interrupt registers. This really gets hairy. + */ + +/* IRSR -- Interrupt Receive Status Ragister */ +#define ASI_IRSR 0x49 +#define IRSR 0x00 +#define IRSR_BUSY 0x020 +#define IRSR_MID(x) (x&0x1f) + +/* IRDR -- Interrupt Receive Data Registers */ +#define ASI_IRDR 0x7f +#define IRDR_0H 0x40 +#define IRDR_0L 0x48 /* unimplemented */ +#define IRDR_1H 0x50 +#define IRDR_1L 0x58 /* unimplemented */ +#define IRDR_2H 0x60 +#define IRDR_2L 0x68 /* unimplemented */ +#define IRDR_3H 0x70 /* unimplemented */ +#define IRDR_3L 0x78 /* unimplemented */ + +/* SOFTINT ASRs */ +#define SET_SOFTINT %asr20 /* Sets these bits */ +#define CLEAR_SOFTINT %asr21 /* Clears these bits */ +#define SOFTINT %asr22 /* Reads the register */ +#define TICK_CMPR %asr23 + +#define TICK_INT 0x01 /* level-14 clock tick */ +#define SOFTINT1 (0x1<<1) +#define SOFTINT2 (0x1<<2) +#define SOFTINT3 (0x1<<3) +#define SOFTINT4 (0x1<<4) +#define SOFTINT5 (0x1<<5) +#define SOFTINT6 (0x1<<6) +#define SOFTINT7 (0x1<<7) +#define SOFTINT8 (0x1<<8) +#define SOFTINT9 (0x1<<9) +#define SOFTINT10 (0x1<<10) +#define SOFTINT11 (0x1<<11) +#define SOFTINT12 (0x1<<12) +#define SOFTINT13 (0x1<<13) +#define SOFTINT14 (0x1<<14) +#define SOFTINT15 (0x1<<15) + +/* Interrupt Dispatch -- usually reserved for cross-calls */ +#define ASR_IDSR 0x48 /* Interrupt dispatch status reg */ +#define IDSR 0x00 +#define IDSR_NACK 0x02 +#define IDSR_BUSY 0x01 + +#define ASI_INTERRUPT_DISPATCH 0x77 /* [4u] spitfire interrupt dispatch regs */ +#define IDCR(x) (((x)<<14)&0x70) /* Store anything to this address to dispatch crosscall to CPU (x) */ +#define IDDR_0H 0x40 /* Store data to send in these regs */ +#define IDDR_0L 0x48 /* unimplemented */ +#define IDDR_1H 0x50 +#define IDDR_1L 0x58 /* unimplemented */ +#define IDDR_2H 0x60 +#define IDDR_2L 0x68 /* unimplemented */ +#define IDDR_3H 0x70 /* unimplemented */ +#define IDDR_3L 0x78 /* unimplemented */ + +/* + * Error registers + */ + +/* Since we won't try to fix async errs, we don't care about the bits in the regs */ +#define ASI_AFAR 0x4d /* Asynchronous fault address register */ +#define AFAR 0x00 +#define ASI_AFSR 0x4c /* Asynchronous fault status register */ +#define AFSR 0x00 + +#define ASI_P_EER 0x4b /* Error enable register */ +#define P_EER 0x00 +#define P_EER_ISAPEN 0x04 /* Enable fatal on ISAP */ +#define P_EER_NCEEN 0x02 /* Enable trap on uncorrectable errs */ +#define P_EER_CEEN 0x01 /* Enable trap on correctable errs */ + +#define ASI_DATAPATH_READ 0x7f /* Read the regs */ +#define ASI_DATAPATH_WRITE 0x77 /* Write to the regs */ +#define P_DPER_0 0x00 /* Datapath err reg 0 */ +#define P_DPER_1 0x18 /* Datapath err reg 1 */ +#define P_DCR_0 0x20 /* Datapath control reg 0 */ +#define P_DCR_1 0x38 /* Datapath control reg 0 */ + + +/* From sparc64/asm.h which I think I'll deprecate since it makes bus.h a pain. */ + +#ifndef _LOCORE +/* + * GCC __asm constructs for doing assembly stuff. + */ + +/* + * ``Routines'' to load and store from/to alternate address space. + * The location can be a variable, the asi value (address space indicator) + * must be a constant. + * + * N.B.: You can put as many special functions here as you like, since + * they cost no kernel space or time if they are not used. + * + * These were static inline functions, but gcc screws up the constraints + * on the address space identifiers (the "n"umeric value part) because + * it inlines too late, so we have to use the funny valued-macro syntax. + */ + +/* + * Apparently the definition of bypass ASIs is that they all use the + * D$ so we need to flush the D$ to make sure we don't get data pollution. + */ + +static __inline__ u_char lduba __P((paddr_t loc, int asi)); +static __inline__ u_short lduha __P((paddr_t loc, int asi)); +static __inline__ u_int lda __P((paddr_t loc, int asi)); +static __inline__ int ldswa __P((paddr_t loc, int asi)); +static __inline__ u_int64_t ldxa __P((paddr_t loc, int asi)); +static __inline__ u_int64_t ldda __P((paddr_t loc, int asi)); + +static __inline__ void stba __P((paddr_t loc, int asi, u_char value)); +static __inline__ void stha __P((paddr_t loc, int asi, u_short value)); +static __inline__ void sta __P((paddr_t loc, int asi, u_int value)); +static __inline__ void stxa __P((paddr_t loc, int asi, u_int64_t value)); +static __inline__ void stda __P((paddr_t loc, int asi, u_int64_t value)); + +#if 0 +static __inline__ unsigned int casa __P((paddr_t loc, int asi, + unsigned int value, unsigned int oldvalue)); +static __inline__ u_int64_t casxa __P((paddr_t loc, int asi, + u_int64_t value, u_int64_t oldvalue)); +#endif + +#ifdef __arch64__ +static __inline__ u_char +lduba(paddr_t loc, int asi) +{ + register unsigned int _lduba_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" lduba [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; wr %%g0, 0x82, %%asi" : + "=&r" (_lduba_v), "=r" (loc): + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; " +" lduba [%1]%%asi,%0; wr %%g0, 0x82, %%asi" : + "=r" (_lduba_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lduba_v); +} +#else +static __inline__ u_char +lduba(paddr_t loc, int asi) +{ + register unsigned int _lduba_v, _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %5; rdpr %%pstate,%1; " +" sllx %3,32,%0; or %0,%2,%0; wrpr %1,8,%%pstate; " +" membar #Sync; lduba [%0]%%asi,%0; wrpr %1,0,%%pstate; " +" andn %2,0x1f,%1; membar #Sync; stxa %%g0,[%1] %5; " +" membar #Sync; wr %%g0, 0x82, %%asi" : + "=&r" (_lduba_v), "=&r" (_pstate) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %3,%%g0,%%asi; sllx %2,32,%0; " +" or %0,%1,%0; lduba [%0]%%asi,%0; wr %%g0, 0x82, %%asi" : "=&r" (_lduba_v) : + "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi)); + } + return (_lduba_v); +} +#endif + +#ifdef __arch64__ +/* load half-word from alternate address space */ +static __inline__ u_short +lduha(paddr_t loc, int asi) +{ + register unsigned int _lduha_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" lduha [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lduha_v), "=r" (loc) : + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; lduha [%1]%%asi,%0; " +" wr %%g0, 0x82, %%asi" : + "=r" (_lduha_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lduha_v); +} +#else +/* load half-word from alternate address space */ +static __inline__ u_short +lduha(paddr_t loc, int asi) { + register unsigned int _lduha_v, _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; rdpr %%pstate,%1; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %5; wrpr %1,8,%%pstate; sllx %3,32,%0; " +" or %0,%2,%0; membar #Sync; lduha [%0]%%asi,%0; wrpr %1,0,%%pstate; " +" andn %2,0x1f,%1; membar #Sync; stxa %%g0,[%1] %5; " +" membar #Sync; wr %%g0, 0x82, %%asi" : + "=&r" (_lduha_v), "=&r" (_pstate) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %3,%%g0,%%asi; sllx %2,32,%0; " +" or %0,%1,%0; lduha [%0]%%asi,%0; wr %%g0, 0x82, %%asi" : "=&r" (_lduha_v) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), "r" (asi)); + } + return (_lduha_v); +} +#endif + + +#ifdef __arch64__ +/* load unsigned int from alternate address space */ +static __inline__ u_int +lda(paddr_t loc, int asi) +{ + register unsigned int _lda_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" lda [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lda_v), "=r" (loc) : + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; lda [%1]%%asi,%0" : + "=r" (_lda_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lda_v); +} + +/* load signed int from alternate address space */ +static __inline__ int +ldswa(paddr_t loc, int asi) +{ + register int _lda_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" ldswa [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lda_v), "=r" (loc) : + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; " +" ldswa [%1]%%asi,%0; wr %%g0, 0x82, %%asi" : + "=r" (_lda_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lda_v); +} +#else /* __arch64__ */ +/* load unsigned int from alternate address space */ +static __inline__ u_int +lda(paddr_t loc, int asi) +{ + register unsigned int _lda_v, _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; rdpr %%pstate,%1;" +" andn %2,0x1f,%0; stxa %%g0,[%0] %5; wrpr %1,8,%%pstate; " +" sllx %3,32,%0; or %0,%2,%0; membar #Sync;lda [%0]%%asi,%0; " +" wrpr %1,0,%%pstate; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %5; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lda_v), "=&r" (_pstate) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %3,%%g0,%%asi; sllx %2,32,%0; " +" or %0,%1,%0; lda [%0]%%asi,%0; wr %%g0, 0x82, %%asi" : "=&r" (_lda_v) : + "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi)); + } + return (_lda_v); +} + +/* load signed int from alternate address space */ +static __inline__ int +ldswa(paddr_t loc, int asi) +{ + register int _lda_v, _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; rdpr %%pstate,%1;" +" andn %2,0x1f,%0; stxa %%g0,[%0] %5; wrpr %1,8,%%pstate; sllx %3,32,%0;" +" or %0,%2,%0; membar #Sync; ldswa [%0]%%asi,%0; wrpr %1,0,%%pstate; " +" andn %2,0x1f,%1; membar #Sync; stxa %%g0,[%1] %5; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_lda_v), "=&r" (_pstate) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %3,%%g0,%%asi; sllx %2,32,%0; " +" or %0,%1,%0; ldswa [%0]%%asi,%0; wr %%g0, 0x82, %%asi" : "=&r" (_lda_v) : + "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi)); + } + return (_lda_v); +} +#endif /* __arch64__ */ + +#ifdef __arch64__ +/* load 64-bit int from alternate address space -- these should never be used */ +static __inline__ u_int64_t +ldda(paddr_t loc, int asi) +{ + register long long _lda_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" ldda [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lda_v), "=&r" (loc) : + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; " +" ldda [%1]%%asi,%0; wr %%g0, 0x82, %%asi" : + "=r" (_lda_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lda_v); +} +#else +/* load 64-bit int from alternate address space */ +static __inline__ u_int64_t +ldda(paddr_t loc, int asi) +{ + register long long _lda_v, _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; rdpr %%pstate,%1;" +" andn %2,0x1f,%0; rdpr %%pstate,%1; stxa %%g0,[%0] %5; wrpr %1,8,%%pstate;" +" sllx %3,32,%0; or %0,%2,%0; membar #Sync; ldda [%0]%%asi,%0; wrpr %1,0,%%pstate; " +" andn %2,0x1f,%1; membar #Sync; stxa %%g0,[%1] %5; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_lda_v), "=&r" (_pstate) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %3,%%g0,%%asi; sllx %2,32,%0; " +" or %0,%1,%0; ldda [%0]%%asi,%0; wr %%g0, 0x82, %%asi" : "=&r" (_lda_v) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), "r" (asi)); + } + return (_lda_v); +} +#endif + + +#ifdef __arch64__ +/* native load 64-bit int from alternate address space w/64-bit compiler*/ +static __inline__ u_int64_t +ldxa(paddr_t loc, int asi) +{ + register unsigned long _lda_v; + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; " +" andn %2,0x1f,%0; stxa %%g0,[%0] %4; membar #Sync; " +" ldxa [%2]%%asi,%0; andn %2,0x1f,%1; membar #Sync; " +" stxa %%g0,[%1] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : "=&r" (_lda_v), "=r" (loc) : + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; " +" ldxa [%1]%%asi,%0; wr %%g0, 0x82, %%asi" : + "=r" (_lda_v) : + "r" ((unsigned long)(loc)), "r" (asi)); + } + return (_lda_v); +} +#else +/* native load 64-bit int from alternate address space w/32-bit compiler*/ +static __inline__ u_int64_t +ldxa(paddr_t loc, int asi) +{ + register unsigned long _ldxa_lo, _ldxa_hi, _loc_hi; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; " +" andn %2,0x1f,%0; rdpr %%pstate,%1; stxa %%g0,[%0] %5; " +" sllx %3,32,%0; wrpr %1,8,%%pstate; or %0,%2,%0; membar #Sync; ldxa [%0]%%asi,%0; " +" wrpr %1,0,%%pstate; andn %2,0x1f,%1; membar #Sync; stxa %%g0,[%1] %5; membar #Sync; " +" srlx %0,32,%1; srl %0,0,%0; wr %%g0, 0x82, %%asi" : + "=&r" (_ldxa_lo), "=&r" (_ldxa_hi) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %4,%%g0,%%asi; sllx %3,32,%0; " +" or %0,%2,%0; ldxa [%0]%%asi,%0; srlx %0,32,%1; " +" srl %0,0,%0;; wr %%g0, 0x82, %%asi" : + "=&r" (_ldxa_lo), "=&r" (_ldxa_hi) : + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi)); + } + return ((((int64_t)_ldxa_hi)<<32)|_ldxa_lo); +} +#endif + +/* store byte to alternate address space */ +#ifdef __arch64__ +static __inline__ void +stba(paddr_t loc, int asi, u_char value) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; stba %1,[%2]%%asi;" +" andn %2,0x1f,%0; membar #Sync; stxa %%g0,[%0] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (loc) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %2,%%g0,%%asi; stba %0,[%1]%%asi; " +" wr %%g0, 0x82, %%asi" : : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi)); + } +} +#else +static __inline__ void +stba(paddr_t loc, int asi, u_char value) +{ + register int _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %5,%%g0,%%asi; sllx %4,32,%0; rdpr %%pstate,%1;" +" or %3,%0,%0; wrpr %1,8,%%pstate; stba %2,[%0]%%asi; wrpr %1,0,%%pstate; " +" andn %0,0x1f,%1; membar #Sync; stxa %%g0,[%1] %6; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_pstate) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %4,%%g0,%%asi; sllx %3,32,%0; " +" or %2,%0,%0; stba %1,[%0]%%asi; wr %%g0, 0x82, %%asi" : "=&r" (_loc_hi) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi)); + } +} +#endif + +/* store half-word to alternate address space */ +#ifdef __arch64__ +static __inline__ void +stha(paddr_t loc, int asi, u_short value) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; stha %1,[%2]%%asi;" +" andn %2,0x1f,%0; membar #Sync; stxa %%g0,[%0] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (loc) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %2,%%g0,%%asi; stha %0,[%1]%%asi; " +" wr %%g0, 0x82, %%asi" : : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi) : "memory"); + } +} +#else +static __inline__ void +stha(paddr_t loc, int asi, u_short value) +{ + register int _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %5,%%g0,%%asi; sllx %4,32,%0; rdpr %%pstate,%1;" +" or %3,%0,%0; wrpr %1,8,%%pstate; stha %2,[%0]%%asi; wrpr %1,0,%%pstate; " +" andn %0,0x1f,%1; membar #Sync; stxa %%g0,[%1] %6; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_pstate) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi), + "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %4,%%g0,%%asi; sllx %3,32,%0; " +" or %2,%0,%0; stha %1,[%0]%%asi; wr %%g0, 0x82, %%asi" : "=&r" (_loc_hi) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi) : "memory"); + } +} +#endif + + +/* store int to alternate address space */ +#ifdef __arch64__ +static __inline__ void +sta(paddr_t loc, int asi, u_int value) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; sta %1,[%2]%%asi;" +" andn %2,0x1f,%0; membar #Sync; stxa %%g0,[%0] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (loc) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %2,%%g0,%%asi; sta %0,[%1]%%asi; " +" wr %%g0, 0x82, %%asi" : : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (asi) : "memory"); + } +} +#else +static __inline__ void +sta(paddr_t loc, int asi, u_int value) +{ + register int _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %5,%%g0,%%asi; sllx %4,32,%0; rdpr %%pstate,%1;" +" or %3,%0,%0; wrpr %1,8,%%pstate; sta %2,[%0]%%asi; wrpr %1,0,%%pstate; " +" andn %0,0x1f,%1; membar #Sync; stxa %%g0,[%1] %6; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_pstate) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi), + "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %4,%%g0,%%asi; sllx %3,32,%0; " +" or %2,%0,%0; sta %1,[%0]%%asi; wr %%g0, 0x82, %%asi" : "=&r" (_loc_hi) : + "r" ((int)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi) : "memory"); + } +} +#endif + +/* store 64-bit int to alternate address space */ +#ifdef __arch64__ +static __inline__ void +stda(paddr_t loc, int asi, u_int64_t value) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; stda %1,[%2]%%asi;" +" andn %2,0x1f,%0; membar #Sync; stxa %%g0,[%0] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (loc) : + "r" ((long long)(value)), "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %2,%%g0,%%asi; stda %0,[%1]%%asi; " +" wr %%g0, 0x82, %%asi" : : + "r" ((long long)(value)), "r" ((unsigned long)(loc)), + "r" (asi) : "memory"); + } +} +#else +static __inline__ void +stda(paddr_t loc, int asi, u_int64_t value) +{ + register int _loc_hi, _pstate; + + _loc_hi = (((u_int64_t)loc)>>32); + if (PHYS_ASI(asi)) { + __asm __volatile("wr %5,%%g0,%%asi; sllx %4,32,%0; rdpr %%pstate,%1; " +" or %3,%0,%0; wrpr %1,8,%%pstate; stda %2,[%0]%%asi; wrpr %1,0,%%pstate;" +" andn %0,0x1f,%1; membar #Sync; stxa %%g0,[%1] %6; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_pstate) : + "r" ((long long)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi), + "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %4,%%g0,%%asi; sllx %3,32,%0; " +" or %2,%0,%0; stda %1,[%0]%%asi; wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi) : + "r" ((long long)(value)), "r" ((unsigned long)(loc)), + "r" (_loc_hi), "r" (asi) : "memory"); + } +} +#endif + +#ifdef __arch64__ +/* native store 64-bit int to alternate address space w/64-bit compiler*/ +static __inline__ void +stxa(paddr_t loc, int asi, u_int64_t value) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %3,%%g0,%%asi; stxa %1,[%2]%%asi;" +" andn %2,0x1f,%0; membar #Sync; stxa %%g0,[%0] %4; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (asi) : + "r" ((unsigned long)(value)), + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %2,%%g0,%%asi; stxa %0,[%1]%%asi; " +" wr %%g0, 0x82, %%asi" : : + "r" ((unsigned long)(value)), + "r" ((unsigned long)(loc)), "r" (asi) : "memory"); + } +} +#else +/* native store 64-bit int to alternate address space w/32-bit compiler*/ +static __inline__ void +stxa(paddr_t loc, int asi, u_int64_t value) +{ + int _stxa_lo, _stxa_hi, _loc_hi; + + _stxa_lo = value; + _stxa_hi = ((u_int64_t)value)>>32; + _loc_hi = (((u_int64_t)(u_long)loc)>>32); + + if (PHYS_ASI(asi)) { + __asm __volatile("wr %7,%%g0,%%asi; sllx %4,32,%1; sllx %6,32,%0; " +" or %1,%3,%1; rdpr %%pstate,%2; or %0,%5,%0; wrpr %2,8,%%pstate; " +" stxa %1,[%0]%%asi; wrpr %2,0,%%pstate; andn %0,0x1f,%1; " +" membar #Sync; stxa %%g0,[%1] %8; membar #Sync; wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_stxa_hi), + "=&r" ((int)(_stxa_lo)) : + "r" ((int)(_stxa_lo)), "r" ((int)(_stxa_hi)), + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %6,%%g0,%%asi; sllx %3,32,%1; sllx %5,32,%0; " +" or %1,%2,%1; or %0,%4,%0; stxa %1,[%0]%%asi; wr %%g0, 0x82, %%asi" : + "=&r" (_loc_hi), "=&r" (_stxa_hi) : + "r" ((int)(_stxa_lo)), "r" ((int)(_stxa_hi)), + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi) : "memory"); + } +} +#endif + +#if 0 +#ifdef __arch64__ +/* native store 64-bit int to alternate address space w/64-bit compiler*/ +static __inline__ u_int64_t +casxa(paddr_t loc, int asi, u_int64_t value, u_int64_t oldvalue) +{ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %4,%%g0,%%asi; casxa [%3]%%asi,%2,%1;" +" andn %3,0x1f,%0; membar #Sync; stxa %%g0,[%0] %5; membar #Sync; " +" wr %%g0, 0x82, %%asi" : + "=&r" (loc), "+r" (value) : + "r" ((unsigned long)(oldvalue)), + "r" ((unsigned long)(loc)), + "r" (asi), "n" (ASI_DCACHE_TAG) : "memory"); + } else { + __asm __volatile("wr %3,%%g0,%%asi; casxa [%1]%%asi,%2,%0; " +" wr %%g0, 0x82, %%asi" : + "+r" (value) : + "r" ((unsigned long)(loc)), "r" (oldvalue), "r" (asi) : + "memory"); + } + return (value); +} +#else +/* native store 64-bit int to alternate address space w/32-bit compiler*/ +static __inline__ u_int64_t +casxa(paddr_t loc, int asi, u_int64_t value, u_int64_t oldvalue) +{ + int _casxa_lo, _casxa_hi, _loc_hi, _oval_hi; + + _casxa_lo = value; + _casxa_hi = ((u_int64_t)value)>>32; + _oval_hi = ((u_int64_t)oldvalue)>>32; + _loc_hi = (((u_int64_t)(u_long)loc)>>32); + +#ifdef __notyet +/* + * gcc cannot handle this since it thinks it has >10 asm operands. + */ + if (PHYS_ASI(asi)) { + __asm __volatile("wr %6,%%g0,%%asi; sllx %1,32,%1; sllx %0,32,%0; " +" sllx %3,32,%3; or %1,%2,%1; rdpr %%pstate,%2; or %0,%4,%0; or %3,%5,%3; " +" wrpr %2,8,%%pstate; casxa [%0]%%asi,%3,%1; wrpr %2,0,%%pstate; " +" andn %0,0x1f,%3; membar #Sync; stxa %%g0,[%3] %7; membar #Sync; " +" sll %1,0,%2; srax %1,32,%1; wr %%g0, 0x82, %%asi " : + "+r" (_loc_hi), "+r" (_casxa_hi), + "+r" (_casxa_lo), "+r" (_oval_hi) : + "r" ((unsigned long)(loc)), + "r" ((unsigned int)(oldvalue)), + "r" (asi), "n" (ASI_DCACHE_TAG)); + } else { + __asm __volatile("wr %7,%%g0,%%asi; sllx %1,32,%1; sllx %5,32,%0; " +" or %1,%2,%1; sllx %3,32,%2; or %0,%4,%0; or %2,%4,%2; " +" casxa [%0]%%asi,%2,%1; sll %1,0,%2; srax %o1,32,%o1; wr %%g0, 0x82, %%asi " : + "=&r" (_loc_hi), "+r" (_casxa_hi), "+r" (_casxa_lo) : + "r" ((int)(_oval_hi)), "r" ((int)(oldvalue)), + "r" ((unsigned long)(loc)), "r" (_loc_hi), + "r" (asi) : "memory"); + } +#endif + return (((u_int64_t)_casxa_hi<<32)|(u_int64_t)_casxa_lo); +} +#endif +#endif /* 0 */ + + + +/* flush address from data cache */ +#define flush(loc) ({ \ + __asm __volatile("flush %0" : : \ + "r" ((unsigned long)(loc))); \ +}) + +/* Flush a D$ line */ +#if 0 +#define flushline(loc) ({ \ + stxa(((paddr_t)loc)&(~0x1f), (ASI_DCACHE_TAG), 0); \ + membar_sync(); \ +}) +#else +#define flushline(loc) +#endif + +/* The following two enable or disable the dcache in the LSU control register */ +#define dcenable() ({ \ + int res; \ + __asm __volatile("ldxa [%%g0] %1,%0; or %0,%2,%0; stxa %0,[%%g0] %1; membar #Sync" \ + : "r" (res) : "n" (ASI_MCCR), "n" (MCCR_DCACHE_EN)); \ +}) +#define dcdisable() ({ \ + int res; \ + __asm __volatile("ldxa [%%g0] %1,%0; andn %0,%2,%0; stxa %0,[%%g0] %1; membar #Sync" \ + : "r" (res) : "n" (ASI_MCCR), "n" (MCCR_DCACHE_EN)); \ +}) + +/* + * SPARC V9 memory barrier instructions. + */ +/* Make all stores complete before next store */ +#define membar_storestore() __asm __volatile("membar #StoreStore" : :) +/* Make all loads complete before next store */ +#define membar_loadstore() __asm __volatile("membar #LoadStore" : :) +/* Make all stores complete before next load */ +#define membar_storeload() __asm __volatile("membar #StoreLoad" : :) +/* Make all loads complete before next load */ +#define membar_loadload() __asm __volatile("membar #LoadLoad" : :) +/* Complete all outstanding memory operations and exceptions */ +#define membar_sync() __asm __volatile("membar #Sync" : :) +/* Complete all outstanding memory operations */ +#define membar_memissue() __asm __volatile("membar #MemIssue" : :) +/* Complete all outstanding stores before any new loads */ +#define membar_lookaside() __asm __volatile("membar #Lookaside" : :) + +#ifdef __arch64__ +/* read 64-bit %tick register */ +#define tick() ({ \ + register u_long _tick_tmp; \ + __asm __volatile("rdpr %%tick, %0" : "=r" (_tick_tmp) :); \ + _tick_tmp; \ +}) +#else +/* read 64-bit %tick register on 32-bit system */ +#define tick() ({ \ + register u_int _tick_hi = 0, _tick_lo = 0; \ + __asm __volatile("rdpr %%tick, %0; srl %0,0,%1; srlx %0,32,%0 " \ + : "=r" (_tick_hi), "=r" (_tick_lo) : ); \ + (((u_int64_t)_tick_hi)<<32)|((u_int64_t)_tick_lo); \ +}) +#endif + +extern void next_tick __P((long)); +#endif diff --git a/sys/arch/sparc64/include/frame.h b/sys/arch/sparc64/include/frame.h new file mode 100644 index 00000000000..d663cc2fcf4 --- /dev/null +++ b/sys/arch/sparc64/include/frame.h @@ -0,0 +1,134 @@ +/* $NetBSD: frame.h,v 1.9 2001/03/04 09:28:35 mrg Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Sparc stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + */ +#ifndef _LOCORE +#ifndef SUN4U +struct frame { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + struct frame *fr_fp; /* space to save frame pointer (%i6) */ + int32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#else +struct frame32 { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int32_t fr_fp; /* space to save frame pointer (%i6) */ + u_int32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#endif +#endif + +/* + * CCFSZ (C Compiler Frame SiZe) is the size of a stack frame required if + * a function is to call C code. It should be just 64, but Sun defined + * their frame with space to hold arguments 0 through 5 (plus some junk), + * and varargs routines (such as kprintf) demand this, and gcc uses this + * area at times anyway. + */ +#define CCFSZ 96 + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tall a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +#if !defined(_LOCORE) && !defined(_LIBC) +struct frame64 { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int64_t fr_fp; /* space to save frame pointer (%i6) */ + u_int64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame64*)(f->fr_fp+BIAS)) +#endif + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + diff --git a/sys/arch/sparc64/include/trap.h b/sys/arch/sparc64/include/trap.h new file mode 100644 index 00000000000..c2efbd6781c --- /dev/null +++ b/sys/arch/sparc64/include/trap.h @@ -0,0 +1,152 @@ +/* $NetBSD: trap.h,v 1.4 1999/06/07 05:28:04 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +#ifndef _MACHINE_TRAP_H +#define _MACHINE_TRAP_H + +/* trap vec (pri) description */ +/* 0x000 unused */ +#define T_POR 0x001 /* (0) power on reset */ +#define T_WDR 0x002 /* (1) watchdog reset */ +#define T_XIR 0x003 /* (1) externally initiated reset */ +#define T_SIR 0x004 /* (1) software initiated reset */ +#define T_RED_EXCEPTION 0x005 /* (1) RED state exception */ +/* 0x006 unused */ +/* 0x007 unused */ +#define T_INST_EXCEPT 0x008 /* (5) instruction access exception */ +#define T_TEXTFAULT 0x009 /* (2) ? Text fault */ +#define T_INST_ERROR 0x00a /* (3) instruction access error */ +/* 0x00b unused */ +/* through 0x00f unused */ +#define T_ILLINST 0x010 /* (7) illegal instruction */ +#define T_PRIVINST 0x011 /* (6) privileged opcode */ +/* 0x012 unused */ +/* through 0x01f unused */ +#define T_FPDISABLED 0x020 /* (8) fpu disabled */ +#define T_FP_IEEE_754 0x021 /* (11) ieee 754 exception */ +#define T_FP_OTHER 0x022 /* (11) other fp exception */ +#define T_TAGOF 0x023 /* (14) tag overflow */ +#define T_CLEAN_WINDOW 0x024 /* (10) clean window exception */ +/* through 0x027 unused */ +#define T_DIV0 0x028 /* (15) division routine was handed 0 */ +/* 0x02a unused */ +/* through 0x02f unused */ +#define T_DATAFAULT 0x030 /* (12) address fault during data fetch */ +/* 0x031 unused */ +#define T_DATA_ERROR 0x032 +#define T_DATA_PROT 0x033 /* Data protection ??? */ +#define T_ALIGN 0x034 /* (10) address not properly aligned */ +#define T_LDDF_ALIGN 0x035 /* (10) LDDF address not properly aligned */ +#define T_STDF_ALIGN 0x036 /* (10) STDF address not properly aligned */ +#define T_PRIVACT 0x037 /* (11) privileged action */ +/* 0x038 unused */ +/* through 0x03F unused */ +#define T_ASYNC_ERROR 0x040 /* ???? */ +#define T_L1INT 0x041 /* (31) level 1 interrupt */ +#define T_L2INT 0x042 /* (30) level 2 interrupt */ +#define T_L3INT 0x043 /* (29) level 3 interrupt */ +#define T_L4INT 0x044 /* (28) level 4 interrupt */ +#define T_L5INT 0x045 /* (27) level 5 interrupt */ +#define T_L6INT 0x046 /* (26) level 6 interrupt */ +#define T_L7INT 0x047 /* (25) level 7 interrupt */ +#define T_L8INT 0x048 /* (24) level 8 interrupt */ +#define T_L9INT 0x049 /* (23) level 9 interrupt */ +#define T_L10INT 0x04a /* (22) level 10 interrupt */ +#define T_L11INT 0x04b /* (21) level 11 interrupt */ +#define T_L12INT 0x04c /* (20) level 12 interrupt */ +#define T_L13INT 0x04d /* (19) level 13 interrupt */ +#define T_L14INT 0x04e /* (18) level 14 interrupt */ +#define T_L15INT 0x04f /* (17) level 15 interrupt */ +/* 0x050 unused */ +/* through 0x05F unused */ +#define T_INTVEC 0x060 /* (16) interrupt vector [Interrupt Global Regs]*/ +#define T_PA_WATCHPT 0x061 /* (12) Physical addr data watchpoint */ +#define T_VA_WATCHPT 0x062 /* (11) Virtual addr data watchpoint */ +#define T_ECCERR 0x063 /* (33) ECC correction error */ +#define T_FIMMU_MISS 0x064 /* (2) fast instruction access MMU miss */ +/* through 0x067 unused */ +#define T_FDMMU_MISS 0x068 /* (2) fast data access MMU miss */ +/* through 0x06b unused */ +#define T_FDMMU_PROT 0x06C /* (2) fast data access protection */ +/* through 0x06F unused */ +/* 0x070...0x07f implementation dependent exceptions */ +#define T_SPILL_N_NORM 0x080 /* (9) spill (n=0..7) normal */ +/* through 0x09F unused */ +#define T_SPILL_N_OTHER 0x0a0 /* (9) spill (n=0..7) other */ +/* through 0x0bF unused */ +#define T_FILL_N_NORM 0x0c0 /* (9) fill (n=0..7) normal */ +/* through 0x0dF unused */ +#define T_FILL_N_OTHER 0x0e0 /* (9) fill (n=0..7) other */ +/* through 0x0fF unused */ + +/* beginning of `user' vectors (from trap instructions) - all priority 16 */ +#define T_SUN_SYSCALL 0x100 /* system call */ +#define T_BREAKPOINT 0x101 /* breakpoint `instruction' */ +#define T_UDIV0 0x102 /* division routine was handed 0 */ +#define T_FLUSHWIN 0x103 /* flush windows */ +#define T_CLEANWIN 0x104 /* provide clean windows */ +#define T_RANGECHECK 0x105 /* ? */ +#define T_FIXALIGN 0x106 /* fix up unaligned accesses */ +#define T_INTOF 0x107 /* integer overflow ? */ +#define T_SVR4_SYSCALL 0x108 /* SVR4 system call */ +#define T_BSD_SYSCALL 0x109 /* BSD system call */ +#define T_KGDB_EXEC 0x10a /* for kernel gdb */ + +/* 0x10b..0x1ff are currently unallocated, except the following */ +#define T_SVR4_GETCC 0x120 +#define T_SVR4_SETCC 0x121 +#define T_SVR4_GETPSR 0x122 +#define T_SVR4_SETPSR 0x123 +#define T_SVR4_GETHRTIME 0x124 +#define T_SVR4_GETHRVTIME 0x125 +#define T_SVR4_GETHRESTIME 0x127 +#define T_GETCC 0x132 +#define T_SETCC 0x133 +#define T_SVID_SYSCALL 0x164 +#define T_SPARC_INTL_SYSCALL 0x165 +#define T_OS_VENDOR_SYSCALL 0x166 +#define T_HW_OEM_SYSCALL 0x167 +#define T_RTF_DEF_TRAP 0x168 + +#ifdef _KERNEL /* pseudo traps for locore.s */ +#define T_RWRET -1 /* need first user window for trap return */ +#define T_AST -2 /* no-op, just needed reschedule or profile */ +#endif + +/* flags to system call (flags in %g1 along with syscall number) */ +#define SYSCALL_G2RFLAG 0x400 /* on success, return to %g2 rather than npc */ +#define SYSCALL_G7RFLAG 0x800 /* use %g7 as above (deprecated) */ + +/* + * `software trap' macros to keep people happy (sparc v8 manual says not + * to set the upper bits). + */ +#define ST_BREAKPOINT (T_BREAKPOINT & 0x7f) +#define ST_DIV0 (T_DIV0 & 0x7f) +#define ST_FLUSHWIN (T_FLUSHWIN & 0x7f) +#define ST_SYSCALL (T_SUN_SYSCALL & 0x7f) + +#endif /* _MACHINE_TRAP_H_ */ |